easyexcel操作之名称匹配

news2024/11/19 9:37:37

简单说下需求

现在我有一个excel表格,里面有两张表,分别是a_name表,b_name表,我要在这两张表的基础上新建一张a_b_name表,这张表匹配a,b表的名称,品牌名一样则放在同一行。

示例:

a_name表

奥迪 奥迪A4L 201935 TFSI 进取版 国V	
奥迪 奥迪A4L 201635 TFSI 自动 运动型	
奥迪 奥迪A4L 201630 TFSI 手动 舒适型	
奥迪 奥迪A4L 201630 TFSI 自动 舒适型	
奥迪 奥迪A4L 201635 TFSI 自动 标准型	
奥迪 奥迪A4L 201635 TFSI 自动 舒适型	
奥迪 奥迪A4L 201535 TFSI 纪念舒享版	

请添加图片描述

b_name表

奥迪 奥迪A4L 2016款 奥迪A4L 45 TFSI quattro个性运动型
奥迪 奥迪A4L 2016款 奥迪A4L 45 TFSI quattro运动型
奥迪 奥迪A4L 2015款 奥迪A4L 50 TFSI quattro旗舰型
奥迪 奥迪A4L 2016款 奥迪A4L 30 TFSI 典藏版 自动舒适型
奥迪 奥迪A4L 2016款 奥迪A4L 35 TFSI 典藏版 自动标准型
奥迪 奥迪A4L 2016款 奥迪A4L 35 TFSI 典藏版 S line舒适型

请添加图片描述

a_b_name表

奥迪 奥迪A4L 201935 TFSI 进取版 国V	奥迪 奥迪A4L 2019款 奥迪A4L 35 TFSI 进取型 国V
奥迪 奥迪A4L 201635 TFSI 自动 运动型	奥迪 奥迪A4L 2016款 奥迪A4L 35 TFSI 自动运动型
奥迪 奥迪A4L 201630 TFSI 手动 舒适型	奥迪 奥迪A4L 2016款 奥迪A4L 30 TFSI 手动舒适型
奥迪 奥迪A4L 201630 TFSI 自动 舒适型	奥迪 奥迪A4L 2016款 奥迪A4L 30 TFSI 自动舒适型
奥迪 奥迪A4L 201635 TFSI 自动 标准型	奥迪 奥迪A4L 2016款 奥迪A4L 35 TFSI 自动标准型
奥迪 奥迪A4L 201635 TFSI 自动 舒适型	奥迪 奥迪A4L 2016款 奥迪A4L 35 TFSI 自动舒适型
奥迪 奥迪A4L 201535 TFSI 纪念舒享版	奥迪 奥迪A4L 2015款 奥迪A4L 35 TFSI 百万纪念舒享版型

需要注意的是a和b并不需要完全一样,只需要大部分相同就放在同一行,也就是说直接==比较没用

OK,了解需求后直接开始,我想的是web网页,上传excel表后点击匹配生成,然后生成a_b_name表

1、创建一个maven项目,导入包

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--lombok用来简化实体类:需要安装lombok插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--easyExcel-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.1.1</version>
        </dependency>
    </dependencies>

2、yml配置文件

# 服务端口
server:
  port: 8010
  # 服务名
spring:
  main:
    main:
    banner-mode: off  #关闭banner
  application:
    name: NameMatching
  # 环境设置:dev、test、prod
  profiles:
    active: dev
  #返回json的全局时间格式
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

3、创建实体类

abData

package com.example.namematching.dao;

import lombok.Data;
@Data
public class abData {
    private String abName;
}

abName

@Data
@NoArgsConstructor
@AllArgsConstructor
public class abData {
    @ExcelProperty({"a_name"})  //excel的表头
    private String aName;
    @ExcelProperty({"b_name"})
    private String bName;
}

4、业务代码

先说下解题思路:

1、首先从excel表中获取a,b表的name集合
2、再将这两个集合利用双循环遍历判断,字符串匹配
3、最后将匹配好的集合存入excel表中

1、获取excel表格数据

    //从excel中读取数据
    public List<aData> getExcelData(String fileName, List<aData> dataList, int sheet) {

        ReadListener<aData> listener = new ReadListener<aData>() {
            @Override
            public void onException(Exception exception, AnalysisContext context) {
                // 异常处理逻辑
            }

            @Override
            public void invoke(aData data, AnalysisContext context) {
                dataList.add(data); // 将数据添加到List集合中
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 所有数据读取完成后的逻辑
            }
        };

        //sheet()读哪个工作表
        EasyExcel.read(fileName, aData.class, listener).sheet(sheet).doRead();

        return dataList;

    }

这里要注意的是 aData.class这个对应excel表格的列

请添加图片描述

而aData为

@Data
@NoArgsConstructor
@AllArgsConstructor
public class aData {
    private String aName;
}

2、通过匹配得到a_b_name集合

匹配思路:
    1、获取两个字符串的Jaccard 相似度(这个Jaccard 相似度指两个集合交集和并集的比值)
    2、Jaccard 相似度最大的添加到集合中  

将字符串切割为单词集合
Hashset集合:无序且不重复,提供了两个方法来获取交并集,分别是retainAll和addAll

​ retainAll:交集

​ addAll:并集

举例:

Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3, 4));
Set<Integer> set2 = new HashSet<>(Arrays.asList(3, 4, 5, 6));

boolean changed = set1.retainAll(set2);
System.out.println(set1);      // 输出: [3, 4]
System.out.println(changed);   // 输出: true


Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3));
Set<Integer> set2 = new HashSet<>(Arrays.asList(3, 4, 5, 6));

boolean changed = set1.addAll(set2);
System.out.println(set1);      // 输出: [1, 2, 3, 4, 5, 6]
System.out.println(changed);   // 输出: true

匹配相似字符串的的代码

// 计算 Jaccard 相似度
    private static double calculateJaccardSimilarity(String str1, String str2) {
        Set<String> set1 = new HashSet<>(Arrays.asList(splitString(str1)));
        Set<String> set2 = new HashSet<>(Arrays.asList(splitString(str2)));

        Set<String> intersection = new HashSet<>(set1);
        intersection.retainAll(set2);

        Set<String> union = new HashSet<>(set1);
        union.addAll(set2);

        return (double) intersection.size() / union.size();
    }

    // 切分字符串为单词集合
    private static String[] splitString(String str) {
        return str.split("\\s+");
    }

3、创建表并导入匹配后的数据

如果fileName不存在表则会自动创建excel表

 public void buildSheet(String fileName, List<abData> abData, String sheetName) {
        // 这里 需要指定写用哪个class去写
        try (ExcelWriter excelWriter = EasyExcel.write(fileName, abData.class).build()) {
            // 这里注意 如果同一个sheet只要创建一次
            WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
            excelWriter.write(abData, writeSheet);
        }
    }

4、最后调用方法

注意这里的fileName如果你是部署到服务其中要改为

    void text(){
        //如果不存在则创建
        String fileName = "D:\\spring-blp\\NameMatching\\src\\main\\resources\\static\\车型名称映射.xlsx"; // Excel文件路径

        List<aData> aDataList = new ArrayList<>(); // 存储数据的List集合
        List<aData> bDataList = new ArrayList<>(); // 存储数据的List集合

        aDataList = getExcelData(fileName, aDataList, 0);
        bDataList = getExcelData(fileName, bDataList, 1);

        List<abData> dataList = new ArrayList<>();

        for (int j = 0; j < aDataList.size(); j++) {
            double max=0;
            int index = 0;
            String aName = aDataList.get(j).getAName();

            for (int i = 0; i < bDataList.size(); i++) {
                String bName = bDataList.get(i).getAName();
                double v = calculateJaccardSimilarity(aName, bName);
                if (v==1){
                    dataList.add(new abData(aName,bDataList.get(i).getAName()));
                    break;
                }
                if (max<v){
                    max=v;
                    index=i;
                }

            }
            dataList.add(new abData(aName,bDataList.get(index).getAName()));
        }

        String fileNameAB = "D:\\spring-blp\\NameMatching\\src\\main\\resources\\static\\abName.xlsx"; // Excel文件路径
        buildSheet(fileNameAB,dataList,"a_b_name");

    }

5、运行获得结果

请添加图片描述

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1109640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

月入10.3K,苦逼土木狗转行5G网路优化工程师:对象没了之后,我选择转行!

如果要去某乎平台搜大学生第一劝退专业&#xff0c;土木专业当之无愧。熬夜打灰、肤色比拼、领导大饼……是土木交流贴吧群常见热词。初入土木纷纷立下的“年轻人不怕吃苦的”flag接连打破&#xff0c;提桶跑路似乎成了土木最终归宿。 今天采访的主人公也是万千苦逼土木人中的一…

【苍穹外卖 | 项目日记】第七天

前言&#xff1a; 昨天晚上巨难受&#xff0c;学完之后实在不想写项目日记了&#xff0c;所以就偷了一下懒&#xff0c;今天早上补上昨天的项目日记 目录 前言&#xff1a; 今日完结任务&#xff1a; 今日收获&#xff1a; 学习订单支付的接口&#xff1a; 杂项知识点&…

正确选择数据库安全运维平台的几个原则

目前市面上数据库安全运维平台比较多&#xff0c;企业选择时候往往很纠结&#xff0c;这里我们小编就给大家总结了几个正确选择数据库安全运维平台的原则&#xff0c;希望对大家有用哦&#xff01; 正确选择数据库安全运维平台的几个原则 1、明确自己的需求 不同数据库安全运…

Maven系列第7篇:聚合、继承、单继承问题详解,必备技能!

maven系列目标&#xff1a;从入门开始开始掌握一个高级开发所需要的maven技能。 这是maven系列第7篇。 整个maven系列的内容前后是有依赖的&#xff0c;如果之前没有接触过maven&#xff0c;建议从第一篇看起&#xff0c;本文尾部有maven完整系列的连接。 本篇内容 maven中聚…

数据结构与算法之图: Leetcode 65. 有效数字 (Typescript版)

有效数字 https://leetcode.cn/problems/valid-number/ 描述 有效数字&#xff08;按顺序&#xff09;可以分成以下几个部分&#xff1a; 一个 小数 或者 整数&#xff08;可选&#xff09;一个 ‘e’ 或 ‘E’ &#xff0c;后面跟着一个 整数 小数&#xff08;按顺序&#…

Talk | 阿里巴巴算法专家王潇斌:开箱即用的文本理解大模型

本期为TechBeat人工智能社区第538期线上Talk&#xff01; 北京时间10月18日(周三)20:00阿里巴巴算法专家—王潇斌的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “开箱即用的文本理解大模型”&#xff0c;介绍了他们提出的SeqGPT以及EcomGPT两个文…

Mysql高级——锁(1)

锁 1. 概述 在数据库中&#xff0c;除传统的计算资源&#xff08;如CPU、RAM、I/O等&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源。为保证数据的一致性&#xff0c;需要对并发操作进行控制&#xff0c;因此产生了锁。同时锁机制也为实现MySQL的各个隔…

软件定义存储不能打?这家成立刚三年的公司问鼎全球存储性能榜

软件定义存储&#xff08;Software Defined Storage&#xff0c;简称SDS&#xff09;在性能层面不能打&#xff1f;这恐怕是当前大多数人固有的认知。 如今&#xff0c;这种认知要被彻底打破了。日前&#xff0c;在存储性能委员会&#xff08;Storage Performance Council&…

头歌平台——C文件操作

第1关&#xff1a;使用FILE结构操作文本文件 任务描述 本关要求编写函数ext\fractDigit&#xff0c;该函数从已有的当前目录下的文件a.txt中读取并解析出其中的数值&#xff0c;并将结果写到当前目录下的文件b.txt中。 其中&#xff1a;文件a.txt中包含各种字符&#xff0c;…

一篇文章解密如何轻松实现移动应用的电子和手绘PDF签名功能!

对PDF文件签名是移动设备上越来越普遍的使用需求&#xff0c;本文将描述自动生成/“手绘”签名与如何使用DevExpress Office File API组件来实现在.NET MAUI应用程序中快速合并签名/签名支持之间的区别。 DevExpress Office File API是一个专为C#, VB.NET 和 ASP.NET等开发人员…

C# Onnx Yolov8 Detect 戴口罩检测

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace Onnx…

如何通过命令行进入到mysql?

如何通过命令行进入到mysql&#xff1f; 首先进入到C盘mysql安装目录的bin文件夹&#xff0c;然后在这个文件夹下打开命令行窗口&#xff0c;如下图&#xff1a; 接着输入进入命令mysql -u root -p如下图&#xff1a; 可以发现输入连接命令之后需要让你输入mysql连接密码&am…

层序中序还原二叉树

题目&#xff1a; 样例&#xff1a; 输入 6 0 2 5 1 4 3 1 2 4 0 5 3 输出 0 2 1 4 5 3 思路&#xff1a; 这道题&#xff0c;核心思想就是 结合 层序遍历的性质&#xff0c;根据 中序来判断左右孩子是否存在。 前中后序的遍历实现&#xff0c;主要都是 递归的形式实现遍历…

如何使用Python给图片添加水印

目录 一、安装Pillow库 二、导入Pillow库和需要用到的模块 三、添加水印 四、调用函数并设置参数 五、需要注意的方面 总结 在Python中&#xff0c;我们可以使用Pillow库来处理图像&#xff0c;包括添加水印。Pillow是Python中最流行的图像处理库之一&#xff0c;它支持多…

Android中使用Glide加载圆形图像或给图片设置指定圆角

一、Glide加载圆形头像 效果 R.mipmap.head_icon是默认圆形头像 ImageView mImage findViewById(R.id.image);RequestOptions options new RequestOptions().placeholder(R.mipmap.head_icon).circleCropTransform(); Glide.with(this).load("图像Uri").apply(o…

canvas画布绘制线条样式:粗细,圆角,拐角等

线条的粗线 lineWidth是改变线条的粗线的&#xff0c;默认是一个像素&#xff1a; context.beginPath(); context.moveTo(20, 50); context.lineTo(280, 50); context.lineWidth1; context.stroke();// 如果这里没有beginPath 你猜猜这三条线的宽度分别是多少 context.beginP…

分享一下微信投票小游戏怎么做

微信投票小游戏是一种非常有趣和互动的社交体验&#xff0c;可以促进用户参与和互动&#xff0c;同时也可以为企业或个人带来很多好处。下面我们将探讨如何制作一个微信投票小游戏&#xff0c;以及如何为主题写作一篇文章。 一、确定游戏目的和主题 首先&#xff0c;我们需要确…

AWS Lambda – 函数版本,别名,API网关,CodeDeploy协同

Hello大家好&#xff0c;我们今天继续讨论AWS Lambda的内容。 Lambda函数的版本 Lambda函数的版本和别名是辅助资源&#xff0c;我们可以通过创建这些资源管理函数的部署和调用。 首先&#xff0c;让我们来看一下Lambda 函数版本的概念。您可以使用版本来管理函数的部署。例…

汽车屏类产品(三):抬头显示Head-Up Display(HUD)

前言 你的下一台车,一定要考虑加装一个HUD。 汽车抬头显示器或汽车抬头显示器(也称为汽车HUD)是任何透明的显示器,它可以在汽车中显示数据,而不需要用户将视线从平时的视角移开。这个名字的由来源于飞行员能够在头部“向上”并向前看的情况下查看信息,而不是向下倾斜查…