用于区分内存中对象的Levenshtein类距离算法?

时间:2015-07-23 15:55:00

标签: java algorithm diff levenshtein-distance

Java 8,虽然这个答案应该适用于任何一个lang。

我有一个问题,我需要比较对象,比如Widgets,然后产生一个&#34;差异&#34;它们之间:也就是说,一组步骤,如果遵循这些步骤,会将一个Widget)转换为另一个(目标)。< / p>

class Widget {
    // Properties and such.
}

class WidgetDiffer extends Differ<Widget> {
    List<Transformation> diff(Widget source, Widget target) {
        // The produced list will convert source to target, if executed
        // by some runtime.
    }
}

class WidgetTransformer extends Transformer<Widget> {
    @Override
    Widget transformSourceToTarget(Widget source, List<Transformation> transforms) {
        // Somehow, run 'transforms' on 'source', which *should*
        // produce an object with the same state/properties as
        // the original target.
    }
}

我知道字符串转换的Levenshtein Distance算法,但是:

  • 那只是字符串而不是Widgets;和
  • 它只给你一个整数(将接收器变成目标所需的转换次数),而我需要一个List<Transformation>,当由某个引擎执行时,将源变为目标

我想知道是否有任何已知的算法来执行此类操作。这些算法是否有可能在某个库中存在?!?

2 个答案:

答案 0 :(得分:1)

我将其视为搜索问题。构造一个图形,其中目标节点是所需的窗口小部件,起始节点是要转换的窗口小部件。每个步骤(图中的边缘)表示对窗口小部件的一种可能转换(添加或删除属性)。构建图形后,在其上运行带有路径提取的DFS,您将获得将起始窗口小部件转换为所需步骤所需的步骤(它也将是所需步骤的最小数量)。

答案 1 :(得分:0)

如果小部件只是key-gt;价值袋,那么问题非常简单。

这是一个JavaScript(您可以将其用作Java实现的伪代码)版本。

function diff(src, target) {
  var result = [];
  for(var key in src) {
    if(key in target) { 
      if(src[key] !== target[key]) {
        result.push({op:"update", name:key, value:target[key]});
      }
    } else {
      result.push({op:"delete", name:key});
    }
  }
  for(var key in target) {
    if(!(key in src)) {
      result.push({op:"add", name:key, value:target[key]});
    }
  }
  return result;
}

console.log(JSON.stringify(diff({}, {a:1, b:2, c:3})));
console.log(JSON.stringify(diff({a:1, b:2, c:3}, {})));
console.log(JSON.stringify(diff({a:1, b:2, c:3}, {b:20, c:30, d:40})));

O(srcPropCount * lookupTargetProp + targetPropCount * lookupSrcPropCount)

唯一的操作是添加新属性,更新现有属性和删除属性。