easyexcel操作之名称匹配

简单说下需求

现在我有一个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、运行获得结果

请添加图片描述

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

B64A-消闲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值