【问题标题】:Sequence comparison in javajava中的序列比较
【发布时间】:2009-05-09 11:10:52
【问题描述】:

我正在寻找一种标准算法/代码 (Java),它比较两个整数列表(旧的和新的)并给出第三个结果列表,该列表提供将“旧”列表转换为“新”列表的操作。

例如:

old-> 1, 2, 3, 4
new-> 9, 2, 3, 6, 4

所以结果应该是这样的:

1-, 9+, 2, 3, 4-, 6+, 4+ 

这里是后缀:

  - = Deleted item from old list.
  + = New added item to old list.

和其余的(无后缀)是不变的数字(即值和索引)。我相信使用 LCS(最长公共序列)的东西可以完成这项工作! 但是我真的不知道有没有。

任何指针将不胜感激。

【问题讨论】:

    标签: java collections diff compare sequence


    【解决方案1】:

    Levenshtein distance 算法似乎对你有用(基本上是你提到的 LCS 算法)。只需将您选择的操作记录在另一个表中(在您选择最小值之后,您需要记录哪个操作导致了最小成本,以便以后能够查找)。

    if (seq1[i] == seq2[j] && d[i - 1, j - 1] <= d[i - 1, j] + 1
                           && d[i - 1, j - 1] <= d[i, j - 1] + 1) {
         d[i, j] = d[i - 1, j - 1];
         action[i, j] = MATCHED;
    } else if (d[i - 1, j] < d[i, j - 1]) // If cost of insertion is less:
    {
         d[i, j] = d[i - 1, j] + 1;
         action[i, j] = INSERTION;
    } else {
         d[i, j] = d[i, j - 1] + 1;
         action[i, j] = DELETION;
    }
    

    然后使用action[i, j] 递归地返回整个过程并将所选操作推送到堆栈中。

    【讨论】:

    • 您好,感谢您的回复。对不起,但我真的不明白,如何找到解决方案。多维数组(d)在这里做什么?我如何填充它?基本上,当我只有两个平面列表时,我该如何开始。
    • "d" 是包含子问题解决方案的数组(d[i, j] = 将 a[0..i] 更改为 b[0..j] 所需的最小操作,因此 d[ a.length, b.length] 将是完整问题的解决方案)。如果您熟悉 LCS 或动态规划,您应该很熟悉,否则我建议您阅读 Introduction to Algorithms 或其他地方的 LCS 部分。
    【解决方案2】:

    我用 C# 实现了一些东西。将其移植到 Java ...

    (编辑)

    这里是 Java 版本:

    enum Action {
        UNCHANGED, ADDED, REMOVED
    }
    
    static class DiffResult<T> {
        private T value;
        public Action type;
    
        public DiffResult(T value, Action type) {
            super();
            this.value = value;
            this.type = type;
        }
    
        public T getValue() {
            return value;
        }
    
        public Action getType() {
            return type;
        }
    }
    
    
    public static <T> List<DiffResult<T>> listDiff(List<T> originalList,
            List<T> newList) {
        List<DiffResult<T>> result = new ArrayList<DiffResult<T>>();
    
        int maxCount = Math.max(originalList.size(), newList.size());
        for (int i = 0; i < maxCount; i++) {
            if (newList.size() < i + 1)
                result.add(new DiffResult<T>(originalList.get(i),
                        Action.REMOVED));
            else {
                if (originalList.size() < i + 1) {
                    result.add(new DiffResult<T>(newList.get(i), Action.ADDED));
                } else {
                    if (originalList.get(i).equals(newList.get(i)))
                        result.add(new DiffResult<T>(originalList.get(i),
                                Action.UNCHANGED));
                    else {
                        result.add(new DiffResult<T>(originalList.get(i),
                                Action.REMOVED));
                        result.add(new DiffResult<T>(newList.get(i),
                                Action.ADDED));
                    }
                }
            }
        }
        return result;
    }
    
    public static void main(String[] args) {
        List<Integer> oldList = new ArrayList<Integer>();
        oldList.add(1);
        oldList.add(2);
        oldList.add(3);
        oldList.add(4);
    
        List<Integer> newList = new ArrayList<Integer>();
        newList.add(9);
        newList.add(2);
        newList.add(3);
        newList.add(6);
        newList.add(4);
    
        List<DiffResult<Integer>> diff = listDiff(oldList, newList);
    
        for (DiffResult<Integer> d : diff) {
            System.out.println("Item: " + d.getValue() + " -> " + d.getType());
        }
    }
    

    【讨论】:

      【解决方案3】:

      仅供将来参考。第一个和第二个答案都很好。 第一个答案是我在寻找什么的线索。比较序列的最佳方式。 和, 第二个答案是比较序列的工作代码。但这并没有给出将一个列表转换为另一个列表的最佳结果。但是对于一个简单的差异来说很好!

      谢谢大家的回答!!

      谢谢, 阿布舍克。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-23
        • 1970-01-01
        • 2013-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多