给出一个
数组['/a','/a/b/c/d/e','/b','/b/c','/a/b/c/d','/a','/b']
我希望能够将此数组缩减为:
['/a/b/c/d/e','/b/c']
,即每条唯一路径中最长的路径('/a'
是'/a/b/c/d/e'
的子字符串)
也许我不知道正确的术语,但我已经谷歌搜索了几个小时而且无处可去
我在考虑按元素长度排序,然后对每个元素循环遍历列表,检查indexOf()
直到我到达元素本身
看起来很贵。
编辑 我没有解释得那么好 - 字符串是路径 - 我需要使用mkdirp来创建目录结构,但没有&#39 ; t想多次调用它(mkdir / a / b / c / d / e会创建/ a / b / c,所以如果我有另一条路径/ a / b / c我只想忽略它
答案 0 :(得分:1)
我会对数组进行排序。然后,迭代。对于每个元素,如果它等于下一个元素或它的子字符串,则跳过它。否则,将其添加到动态增长的结构中。最后,将动态增长的结构转换为数组。
你只需要检查下一个项目,因为任何其他东西的前缀都会在它之前按字母顺序排列,直接在最短的字符串之前使用它作为前缀。这会将您的算法降低到O(nlgn)。
幸运的是,'/'出现在ASCII中的字母和数字之前,这将帮助您将其扩展到具有多重文件夹名称的路径。
让我们假设你的原始数组在arr。
var arr = ['/a','/a/b/c/d/e','/b','/b/c','/a/b/c/d','/a','/b'];
arr.sort();
var output = [];
for(var i = 0; i < arr.length; i++)
{
if(i < arr.length - 1 && arr[i + 1].indexOf(arr[i]) == 0 &&
(arr[i].length == arr[i + 1].length || arr[i + 1].charAt(arr[i].length) == "/"))
{
continue;
}
output.push(arr[i]);
}
console.log(output);
在for循环中,对于每个字符串,我们检查后面的数组中是否有另一个字符串;如果不是,该字符串不是另一个路径的前缀。然后,我们检查当前和下一个字符串是否相等。如果没有,我们检查下一个字符串是否以当前字符串开头,以及当前字符串后面的下一个字符是否为下一个字符串中的“/”,这样我们就不会认为“abc / def”是前缀“abc / defghi / jkl”,显然是两条不同的路径。
答案 1 :(得分:1)
您可以检查整个字符串并收集较长的字符串,而无需提前排序。
var array = ['/abc/def', '/abc/defghi/jkl', '/a', '/a/b/c/d/e', '/b', '/b/c', '/efg', '/a/b/c/d', '/a', '/b', '/a/b'],
result = array.reduce(function (r, a) {
r.some(function (b, i, rr) {
var aa = a + '/',
bb = b + '/',
min = Math.min(aa.length, bb.length);
if (aa.slice(0, min) === bb.slice(0, min)) {
if (a.length > b.length) {
rr[i] = a;
}
return true;
}
}) || r.push(a);
return r;
}, []);
console.log(result);
&#13;
答案 2 :(得分:0)
我最终想出了这个 - 感谢评论
let originalArray = ['/abc/def','/abc/defghi/jkl','/a','/a/b/c/d/e','/b','/b/c','/efg','/a/b/c/d','/a','/b','/a/b'];
let uniqueArray = Array.from(new Set(originalArray));
let newArray = [];
uniqueArray.sort();
uniqueArray.forEach((item,index) => {
if (index === uniqueArray.length - 1) {
newArray.push(item);
return;
}
if (uniqueArray[index + 1].indexOf(item + "/") === -1) {
newArray.push(item);
}
});
console.log(newArray)
&#13;