Arrays 将Node.js中数组中的类似字符串分组

Arrays 将Node.js中数组中的类似字符串分组,arrays,node.js,string,comparison,Arrays,Node.js,String,Comparison,假设我在一个数组中有一个不同URL的集合: var source = ['www.xyz.com/Product/1', 'www.xyz.com/Product/3', 'www.xyz.com/Category/1', 'somestring'] 迭代数组并将类似字符串分组到单独的数组中的好方法是什么? 上述示例的预期输出为: var output = [ ['www.xyz.com/Product/1', 'www.xyz.com/Product/3'], ['www.x

假设我在一个数组中有一个不同URL的集合:

var source = ['www.xyz.com/Product/1', 'www.xyz.com/Product/3', 'www.xyz.com/Category/1', 'somestring']
迭代数组并将类似字符串分组到单独的数组中的好方法是什么? 上述示例的预期输出为:

var output = [
    ['www.xyz.com/Product/1', 'www.xyz.com/Product/3'],
    ['www.xyz.com/Category/1'],
    ['somestring']
];
条件

  • source
    中的所有项都可以是随机字符串
  • 逻辑必须能够在有意义的时间内比较和分组大约10万个项目
我发现了一种方法,它可以将一个字符串与一组字符串进行比较。一种方法是迭代源,将每个项与源集合进行比较,并将规则应用于具有类似分数的项的分组。然而,我想这将是可怕的效率低下


有人能给我一个有效的方法来完成我需要的吗?

你的意图并没有具体化,但是如果要从一个随机的草堆中找到一个最近的项目,我可能会尝试建立一个哈希树

或者,这可能是作弊,我会让图书馆帮我做。基本上是一个纯JS lucene索引,我会将您的数组放入其中,并对其进行查询以获得类似的字符串。我以前在lunr.js中有过相当大的数据集,它的性能非常好,没有比附近有elasticsearch集群更好的地方,但仍然令人印象深刻


如果您提供更多关于您尝试执行的操作的详细信息,我可以提供更多的详细信息,甚至可以提供一些示例代码。

我能想到的最佳解决方案是将字符串相互比较,并测试它们之间的差异。有一种算法可以做到这一点,这就是算法:

Levenshtein距离是一种测量距离的字符串度量 两个序列之间的差异。非正式地说,Levenshtein距离 两个单词之间是单个字符编辑的最小数量 (即插入、删除或替换)需要更改一个 一个字换成另一个字


我们可以在以下各项之上轻松创建Levenshtein过滤器:

const levenshtein=require('fast-levenshtein');
常量levenshteinFilter=(源,最大值=5)=>{
让_源,匹配,x,y;
_source=source.slice();
匹配项=[];
对于(x=\u source.length-1;x>=0;x--){
让输出=_source.splice(x,1);
对于(y=_source.length-1;y>=0;y--){

if(levenshtein.get(output[0],_source[y])如果源包含所有随机URL,下面的函数将给出问题中所示的预期输出

function filter (source) {
  var output = []
  source.forEach((svalue) => {
    if (output.length === 0) {
      output.push([svalue])
    } else {
      var done = false
      output.forEach((tarr) => {
        if (!done) {
          tarr.forEach((tvalue) => {
            if (svalue.indexOf('/') > -1 && svalue.split('/').slice(0, 2).join('/') == tvalue.split('/').slice(0, 2).join('/')) {
              tarr.push(svalue)
              done = true
            }
          })
        }
      })
      if (!done) {
        output.push([svalue])
        done = true
      }
    }
  })
  return output
}
MinHash()怎么样


它被设计用来查找重复的网页。所以我想你可以url.split('/'))并将每个url视为一组单词。

根据您的示例测试,我可以建议您实现一个存储字符串的方法。之后,您可以定义一个标准来对这些字符串进行聚类。

我根据Dice的系数将user7560588的代码修改为用户字符串相似性,这比Levenshtein距离要好得多

您可以将接受率从0调整为1,即1是100%匹配。因此,设置正确的接受值对您来说具有更好的分辨率

它所做的是循环数组中的值,比较两个字符串,如果匹配,将它们分组。 该库还可以将字符串与字符串数组进行比较,并在数组中返回相应的评级

var stringSimilarity = require("string-similarity");

const stringFilter = (source, rate = 0.85) => {
  let _source, matches, x, y;
  _source = source.slice();
  matches = [];
  for (x = _source.length - 1; x >= 0; x--) {
    let output = _source.splice(x, 1);

    for (y = _source.length - 1; y >= 0; y--) {
      var match = stringSimilarity.compareTwoStrings(output[0], _source[y]);
      console.log(output[0], _source[y], match);
      if (match > rate) {
        output.push(_source[y]);
        _source.splice(y, 1);
        x--;
      }
    }
    matches.push(output);
  }
  return matches;
};

let source = ['www.xyz.com/Product/1', 'www.xyz.com/Product/3', 'www.xyz.com/Category/1', 'somestring'];
let output = stringFilter(source);
console.log(output);
结果

somestring www.xyz.com/Category/1 0.06666666666666667
somestring www.xyz.com/Product/3 0.06896551724137931
somestring www.xyz.com/Product/1 0.06896551724137931
www.xyz.com/Category/1 www.xyz.com/Product/3 0.5365853658536586
www.xyz.com/Category/1 www.xyz.com/Product/1 0.5853658536585366
www.xyz.com/Product/3 www.xyz.com/Product/1 0.95
[
  [ 'somestring' ],
  [ 'www.xyz.com/Category/1' ],
  [ 'www.xyz.com/Product/3', 'www.xyz.com/Product/1' ]
]

所以在这个例子中有一个清晰的模式,但似乎你问的字符串可以是任何东西?对吗?@aw04是的,没有清晰的模式字符串可以是任何东西。正如我所写的:源代码中的所有项目都可以是随机字符串祝你好运:)不过,请注意,类似的分数概念太简单了,你只看到一个字符串与另一个字符串的关系,而不是它们之间的关系。我唯一能想到的是,第一次尝试,以某种方式找出不同的数组组,但这听起来像是一个相当复杂的算法。你完全正确,但我认为肯定已经有了存在完成此类比较的算法(Node.js中未实现mb)我只是不知道。所以我希望有人能把我推向正确的方向:)尽管我提出了一个库,使用了与您的解决方案相同的算法。我还没有衡量性能,但感谢您的回答!应该是
levenshtein.get(
?@JohnJones谢谢你注意到这一点。这看起来很有趣。我会更深入地看一看,谢谢!
somestring www.xyz.com/Category/1 0.06666666666666667
somestring www.xyz.com/Product/3 0.06896551724137931
somestring www.xyz.com/Product/1 0.06896551724137931
www.xyz.com/Category/1 www.xyz.com/Product/3 0.5365853658536586
www.xyz.com/Category/1 www.xyz.com/Product/1 0.5853658536585366
www.xyz.com/Product/3 www.xyz.com/Product/1 0.95
[
  [ 'somestring' ],
  [ 'www.xyz.com/Category/1' ],
  [ 'www.xyz.com/Product/3', 'www.xyz.com/Product/1' ]
]