2

我正在寻找一种标准算法/代码(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(最长公共序列)的东西可以完成这项工作!但我真的无法弄清楚是否有任何东西。

任何指针将不胜感激。

4

3 回答 3

3

Levenshtein 距离算法似乎对你有用(基本上是你提到的 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]递归地返回整个过程并将所选操作推送到堆栈中。

于 2009-05-09T11:27:46.653 回答
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());
    }
}
于 2009-05-09T11:58:01.107 回答
0

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

谢谢大家的回答!!

谢谢,阿布舍克。

于 2009-05-28T15:08:10.737 回答