我正在尝试将列表缩小为较短的列表,只是普通文件系统路径。试图找到所有普通的祖父母,并只将其列入最终名单。这是目标 :目标是我们必须消除列表中所有包含父目录的目录。
一种更好的短语表达方式可能是: 目标是我们必须消除列表中存在该路径的父目录的所有路径。
说我有这个输入和预期的输出:
const input = [
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman",
"/home/oleg/WebstormProjects/oresoftware/sumanjs",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch"
];
const output = [
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs",
];
const getReducedList = function (input) {
return input
.sort((a, b) => (a.length - b.length))
.reduce((a, b) => {
// console.log('a:', a, 'b:', b);
const s = !a.some(v => {
return b.startsWith(v);
});
if (s) {
a.push(b);
}
return a;
}, []);
};
console.log(getReducedList(input));
getReducedList
函数似乎可以在我们的第一个测试用例中使用,将5减少到2。但是,如果我们添加第二个测试用例,这将变得很奇怪: < / p>
如果我从原始列表中删除了一个项目,并将其更改为以下4个列表:
const input = [
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch"
];
然后我期望得到此输出(4个相同的列表):
const output = [
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch"
];
之所以我希望/希望使用相同的4,是因为列表中没有项目在列表中的其他位置具有父目录。但是我实际上得到的输出是2的列表,这是不正确的:
const output = [
'/home/oleg/WebstormProjects/oresoftware/r2g',
'/home/oleg/WebstormProjects/oresoftware/sumanjs/suman'
];
有人知道我该如何解决这个问题以获得预期的结果吗?一个答案需要同时满足两个测试用例。
为清楚起见,如果将"/home/oleg"
添加到原始列表,则"/home/oleg"
应该是输出中的唯一条目。
答案 0 :(得分:2)
我认为您可以使用非常简单的递归函数来完成此操作。您只需按长度排序,然后递归弹出最短的字符串,将其添加到结果中,使用该值过滤数组,然后递归:
const input = [
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman",
"/home/oleg/WebstormProjects/oresoftware/sumanjs",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch"
];
input.sort((a,b) => b.length - a.length)
function getPrefixes(list, res =[]) {
if (list.length < 1) return res
let next = list.pop()
res.push(next)
return getPrefixes(list.filter(u => !u.startsWith(next + '/')), res)
}
console.log(getPrefixes(input))
答案 1 :(得分:1)
您可以添加斜线用于查找,并在下一个元素中找到时弹出最后一个值。
该提案使用按值排序的列表,而不是按字符串的长度,因为它需要一个排序后的列表来补偿下一个元素。
function uniqueFolder(array) {
return array
.sort()
.reduce((a, b) => {
if (b.startsWith(a[a.length - 1] + '/')) {
a.pop();
}
a.push(b);
return a;
}, []);
}
function commonPath(array) {
return array
.sort()
.reduce((a, b) => {
if (!b.includes(a[a.length - 1])) {
a.push(b);
}
return a;
}, []);
}
const input = [ "/home/oleg/WebstormProjects/oresoftware/r2g", "/home/oleg/WebstormProjects/oresoftware/sumanjs/suman", "/home/oleg/WebstormProjects/oresoftware/sumanjs", "/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types", "/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch"];
console.log(uniqueFolder(input));
console.log(commonPath(input));
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 2 :(得分:1)
您可以简单地使用节点的path
模块
const path = require('path');
const input = [
'/home/oleg/WebstormProjects/oresoftware/r2g',
'/home/oleg/WebstormProjects/oresoftware/sumanjs/suman',
'/home/oleg/WebstormProjects/oresoftware/sumanjs',
'/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types',
'/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch'
];
const s = new Set();
const out = [];
input.forEach(e => {
let p = path.dirname(e);
if (! s.has(p)) {
s.add(p);
out.push(e);
}
});
console.log(out);
如果您想...,forEach显然可以用reduce代替...
答案 3 :(得分:1)
当下一个值在前一个值之后没有 last 前斜杠时,您需要避免匹配。
const input = [
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman",
"/home/oleg/WebstormProjects/oresoftware/sumanjs",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch"
];
const getReducedList = (set => input => input.filter(b =>
!set.has(b.substr(0, b.lastIndexOf("/")))))(new Set(input));
console.log(getReducedList(input));
逻辑是将所有路径放入集合中,然后检查每个路径的父路径是否在集合中。路径的父级是具有所有字符的路径,直到最后一个/
为止(不包括最后一个字符)。
从输入中删除第二个条目不会更改输出。 suman
与suman-types
和suman-watch
的处理方式相同。
这是更详细的ES5版本(用普通对象替换Set
):
const input = [
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman",
"/home/oleg/WebstormProjects/oresoftware/sumanjs",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch"
];
function getReducedList(input) {
var hash = {};
input.forEach(function(path) {
hash[path] = true;
});
return input.filter(function (b) {
return !hash[b.substr(0, b.lastIndexOf("/"))];
}, []);
}
console.log(getReducedList(input));
答案 4 :(得分:1)
它虽然没有其他缺点,但仍无法进行排序。
编辑:必须添加排序才能正常工作
const input = [
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman",
"/home/oleg/WebstormProjects/oresoftware/sumanjs",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch"
];
const input2 = [
"/home/oleg/WebstormProjects/oresoftware",
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch"
];
function getParents(input) {
return input.sort((a, b) => a.length - b.length)
.reduce((acc, a) => {
const index = acc.findIndex(b => b.startsWith(a) || a.startsWith(b));
const slashDiff = index > 0 ? a.split('/').length === acc[index].split('/').length : false;
if (index === -1 || slashDiff) {
return [...acc, a];
}
acc.splice(index, 1, a.length < acc[index].length ? a : acc[index])
return acc;
}, []);
}
console.log(getParents(input));
console.log(getParents(input2));
答案 5 :(得分:1)
看起来我们只需要更改一行即可。这是原始文件:
const getReducedList = function (input) {
return input
.sort((a, b) => (a.length - b.length))
.reduce((a, b) => {
const s = !a.some(v => {
return b.startsWith(v);
});
if (s) {
a.push(b);
}
return a;
}, []);
};
我们需要改为一行:
return b.startsWith(v + '/');
答案 6 :(得分:0)
如果可以使用es6中的集合,则可以根据目录长度进行排序,然后继续推送到集合。
答案 7 :(得分:0)
const input = [
"/home/oleg/WebstormProjects/oresoftware/r2g",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman",
"/home/oleg/WebstormProjects/oresoftware/sumanjs",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-watch",
"/home/oleg/WebstormProjects/oresoftware/sumanjs/suman-types-blabla",
];
let ouput = input.sort().reduce((a, c)=> {
let d = true;
for (let j =0; j< a.length; j++){
if(c.startsWith(a[j]+'/')) {
d=false;
break;}
}
if (d) a.push(c);
return a;
},[]);
console.log(ouput);