【动态规划:最短编辑路径】的应用:excel diff功能

开篇说明

如果在这里获得过启发和思考,希望点赞支持!对于内容有不同的看法欢迎来信交流。
技术栈 >> java
邮箱 >> 15673219519@163.com

描述
  • 在游戏行业中通常使用excel做配表,修改配表是一个频繁的操作。在修改之后,为减少认为的误操作。为此我们需要指定两个版本的配表进行对比功能。
  • 本文excel diff不限于游戏行业,适用于任意两个excel直接的对比。
动态规划:最短编辑路径 介绍
  • 最短编辑路径,简单的说就是"字符串1"改成"字符串2"需要经过多少步;如字符串"ABC"改成"ADCE"需要如下步骤
    • 1,删除B
    • 2,新增D
    • 3,新增E
      通过以上步骤我们就可以实现:字符串"ABC"改成"ADCE"
  • 通过上面的我们可以知道,这些步骤就是两个字符串之间的不同。
  • 动态规划-最短编辑路径
实现思路
  • 通过上面介绍的字符串"ABC"改成"ADCE"案例,类比到excel就是每一行的删除/新增就可以重任意一个excel表格变成另一个excel表格。其中变化的每一步就是这两个excel的不同之处。
  • excel我们可以理解就是可以通过一个二维数组保存数据,这里我们做一个降维操作,把它变成一个一维数组。也就是每一行的数据当作一个元素处理。
实现效果

在这里插入图片描述

实现步骤
  • 第一步: 读取excel的数据,并且把每一行的数据当作一个元素,整个excel表格的数据可以直接存入一个List中。
  • 第二步:写一个方法传入两个List,返回差异List
    @Data
    @AllArgsConstructor
    public static class Row {
        // 格子信息
        private List<Cell> cells;
        // diff + - =
        private String diff;
        // 行号
        private Integer rowNum;
        // 旧行号
        private Integer oldRowNum;
    }
private static List<Row> compareLines(List<Row> lines1, List<Row> lines2) {

        List<Row> differences = new ArrayList<>();
        int[][] LCS = new int[lines1.size() + 1][lines2.size() + 1];

        // 计算LCS矩阵
        for (int i = 1; i <= lines1.size(); i++) {
            for (int j = 1; j <= lines2.size(); j++) {
                if (lines1.get(i - 1).equals(lines2.get(j - 1))) {
                    LCS[i][j] = LCS[i - 1][j - 1] + 1;
                } else {
                    LCS[i][j] = Math.max(LCS[i - 1][j], LCS[i][j - 1]);
                }
            }
        }

        // 从LCS矩阵中提取差异
        int i = lines1.size();
        int j = lines2.size();
        while (i > 0 || j > 0) {
            if (i > 0 && j > 0 && lines1.get(i - 1).equals(lines2.get(j - 1))) {
                Row row = lines2.get(j - 1);
                row.setDiff("=");
                row.setRowNum(j);
                row.setOldRowNum(i);
                differences.add(row);
                i--;
                j--;
            } else if (j > 0 && (i == 0 || LCS[i][j - 1] >= LCS[i - 1][j])) {// +
                Row row = lines2.get(j - 1);
                row.setDiff("+");
                row.setRowNum(j);
                differences.add(row);
                j--;
            } else { // -
                Row row = lines1.get(i - 1);
                row.setDiff("-");
                row.setRowNum(i);
                row.setOldRowNum(i);
                differences.add(row);
                i--;
            }
        }
        // 翻转差异列表
        List<Row> reversed = new ArrayList<>();
        for (int k = differences.size() - 1; k >= 0; k--) {
            reversed.add(differences.get(k));
        }
        return reversed;
    }
  • 第三步:compareLines返回的就是excel的diff结果。需要新增那些行,需要删除那些行。就可以由excel1编辑成excel2。
拓展
  • 目前上面的实现仅仅diff到行的维度,那么如何实现diff中每个格子的变化。这边需要分情况考虑…
  • 最终的两个excel的行数是否发生变化。
  • 如果excel1(10行),变化后的excel(20行),这种目前是没有我没有想到很好的处理到每个格子,只能diff到行。
  • 如果excel1(10行),变化后的excel(10行),可以根据行号相同的行数再次通过compareLines方法找出差异格子,注意这里传入的应该是格子的数据列表。
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
可以使用最短编辑距离算法和Java-diff-utils库来编写比对程序。最短编辑距离算法可以用来计算两个字符串之间的最小编辑操作数,而Java-diff-utils库可以帮助我们生成两个字符串之间的差异。 首先,你需要导入Java-diff-utils库到你的项目中。你可以在Maven或Gradle的配置文件中添加相应的依赖项来引入该库。 接下来,你可以使用最短编辑距离算法(例如Levenshtein距离)来计算两个字符串之间的最小编辑操作数。你可以实现一个函数来计算最小编辑距离,例如: ```java public static int calculateEditDistance(String str1, String str2) { int m = str1.length(); int n = str2.length(); int[][] dp = new int[m + 1][n + 1]; for (int i = 0; i <= m; i++) { dp[i][0] = i; } for (int j = 0; j <= n; j++) { dp[0][j] = j; } for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (str1.charAt(i - 1) == str2.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = 1 + Math.min(dp[i - 1][j - 1], Math.min(dp[i][j - 1], dp[i - 1][j])); } } } return dp[m][n]; } ``` 然后,你可以使用Java-diff-utils库来生成两个字符串之间的差异。你可以实现一个函数来比较两个字符串,并返回差异结果,例如: ```java public static String compareStrings(String str1, String str2) { Patch<String> patch = DiffUtils.diff(Arrays.asList(str1.split("\\n")), Arrays.asList(str2.split("\\n"))); List<Delta<String>> deltas = patch.getDeltas(); StringBuilder result = new StringBuilder(); for (Delta<String> delta : deltas) { result.append(delta).append("\n"); } return result.toString(); } ``` 在这个例子中,我们将两个字符串按行分割,并使用Java-diff-utils库中的`DiffUtils.diff`方法来获取差异。然后,我们遍历差异列表,并将每个差异添加到结果字符串中。 请注意,这只是一个简单的示例,你可能需要根据你的实际需求进行适当的修改和调整。 希望这能帮助到你!如果你还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

放码过来_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值