Arrays 将Node.js中数组中的类似字符串分组
假设我在一个数组中有一个不同URL的集合: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
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' ]
]