确保不存在重复的目录路径

我正在编写一个脚本,其中用户选择目录,然后将这些目录存储在数组属性中,以便可以递归抓取它们。


{

  "archives": [

    "C:\\AMD\\Packages",

    "C:\\Users",

    "C:\\Windows",

    "D:\\",

    "E:\\Pictures\\Birthday"

  ]

}

我显然不想存储重复的路径或其他路径包含的路径。例如,如果用户要选择一个新文件夹添加到数组中,E:\\Pictures,E:\\Pictures\\Birthday则将被丢弃并替换为它,因为E:\\Pictures包含E:\\Pictures\\Birthday。


{

  "archives": [

    "C:\\AMD\\Packages",

    "C:\\Users",

    "C:\\Windows",

    "D:\\",

    "E:\\Pictures"

  ]

}

我知道这可以通过解析所有正在考虑的值(即['C:', 'AMD', 'Packages'], [...], ...等)然后将它们相互比较来完成。然而,这似乎非常密集,尤其是当路径数组变得更大并且目录路径更长时。


您也可以通过将字符串与includes. 例如,如果A包含B或B包含A,则将它们拆分,并丢弃长度较长的。


for (const dir of dirs){

  if (newPath.includes(dir) || dir.includes(newPath)){

    if (newPath.split('\\') < dir.split('\\')){

      // remove dir from json object and replace it with newPath

    }

  } else {

    pathArray.push(dir)

  }

}

阅读以下答案之一后,我才意识到该includes方法遇到了比较相似但独特的路径即C:\Users和 的问题C:\User。


虽然必须有更好的方法来做到这一点?


当年话下
浏览 147回答 2
2回答

慕桂英4014372

这个功能会给你你想要的结果。它首先查看路径的父级是否存在于档案中,如果存在,则不执行任何操作。如果没有,则删除路径的所有子项,然后插入新路径。更新我delim为该函数添加了一个输入,使其也可用于 unix/MacOS 样式的文件名。let data = {&nbsp; "archives": [&nbsp; &nbsp; "C:\\AMD\\Packages",&nbsp; &nbsp; "C:\\Users",&nbsp; &nbsp; "C:\\Windows",&nbsp; &nbsp; "D:\\",&nbsp; &nbsp; "E:\\Pictures"&nbsp; ]};const add_to_archives = (path, data, delim) => {&nbsp; // does the parent of this path already exist? if so, nothing to do&nbsp; if (data.archives.reduce((c, v) =>&nbsp; &nbsp; &nbsp; c || path.indexOf(v.slice(-1) == delim ? v : (v + delim)) === 0, false)) return data;&nbsp; // not found. remove any children of this path&nbsp; data.archives = data.archives.filter(v => v.indexOf(path.slice(-1) == delim ? path : (path + delim)) !== 0);&nbsp; // and add the new path&nbsp; data.archives.push(path);&nbsp; return data;}add_to_archives("E:\\Pictures\\Too", data, "\\");console.log(data);add_to_archives("E:\\PicturesToo", data, "\\");console.log(data);add_to_archives("D:\\Documents", data, "\\");console.log(data);add_to_archives("C:\\AMD", data, "\\");console.log(data);data = {&nbsp; "archives": [&nbsp; &nbsp; "/var/www/html/site",&nbsp; &nbsp; "/etc",&nbsp; &nbsp; "/usr/tim",&nbsp; &nbsp; "/bin"&nbsp; ]};add_to_archives("/var/www/html/site2", data, "/");console.log(data);add_to_archives("/etc/conf.d", data, "/");console.log(data);add_to_archives("/usr", data, "/");console.log(data);add_to_archives("/var/www/html", data, "/");console.log(data);.as-console-wrapper {&nbsp; max-height: 100% !important;}

四季花海

我们可以通过使用前缀树来解决这个问题目的是限制我们检查包含或“包含”的路径数量。如果您有很多兄弟姐妹(树遍历 + 查找作为每个文件夹的键),这种方法可能很有用。如果您经常在archives算法tree = {}foreach path&nbsp; &nbsp; split the path in folders (one may iterate with substring but it is worth it?)&nbsp; &nbsp; try to match folders of that path while traversing the tree&nbsp; &nbsp; if you encounter a stop node, skip to next path&nbsp; &nbsp; if not,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; if your path end on an existing node&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mark that node as a stop node&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drop the children of that node (you can let them be, though)&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; include the remaining folders of the path as node in tree&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mark the last node as a stop node实施请注意,如果路径包含名为“stop”的文件夹,则下面的实现将失败。按主观偏好顺序使用Map和Symbol('stop')或一棵真正的树(至少不要在 boolean 旁边存储文件夹stop)如果您设法到达路径的尽头,请不要假设任何停止节点并始终丢弃子节点希望没有人试图比你更聪明并重命名stop为一些晦涩的 - 文件夹将不存在 -lolol_xxzz9_stopfunction nodupes(archives){&nbsp; &nbsp; tree = {};&nbsp; &nbsp; archives.forEach(arch=>{&nbsp; &nbsp; &nbsp; &nbsp; const folders = arch.split('\\');&nbsp; &nbsp; &nbsp; &nbsp; folders.splice(1,1);&nbsp; &nbsp; &nbsp; &nbsp; //case of empty string such as D:\\\&nbsp; &nbsp; &nbsp; &nbsp; if(folders[folders.length-1].length==0){folders.pop();}&nbsp; &nbsp; &nbsp; &nbsp; let cur = tree;&nbsp; &nbsp; &nbsp; &nbsp; let dropped = false;&nbsp; &nbsp; &nbsp; &nbsp; let lastFolderIndex = 0;&nbsp; &nbsp; &nbsp; &nbsp; let ok = folders.every((folder,i)=>{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(cur[folder]){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(cur[folder].stop){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dropped = true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cur = cur[folder];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cur[folder] = {}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cur = cur[folder];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lastFolderIndex = i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; if(ok){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cur.stop = true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //delete (facultatively) the subfolders&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(lastFolderIndex < folders.length-1){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log('cleanup', folders, 'on node', cur)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object.keys(cur).forEach(k=>{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(k != 'stop'){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delete cur[k];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; });&nbsp; &nbsp; //console.log('tree', JSON.stringify(tree,null,1));&nbsp; &nbsp; //dfs on the tree to get all the paths to... the leaves&nbsp; &nbsp; let dfs = function(tree,paths,p){&nbsp; &nbsp; &nbsp; &nbsp; if(tree.stop){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return paths.push(p.join('\\\\'));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; Object.keys(tree).forEach(k=>{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dfs(tree[k], paths, p.concat(k));&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }&nbsp; &nbsp; let paths = [];&nbsp; &nbsp; dfs(tree, paths,[]);&nbsp; &nbsp; return paths;}let archives = [&nbsp; &nbsp; 'C:\\\\ab',&nbsp; &nbsp; 'D:\\\\', //just some root&nbsp; &nbsp; 'D:\\\\ab',//be dropped&nbsp; &nbsp; 'D:\\\\abc',//dropped as well&nbsp; &nbsp; 'F:\\\\abc\\\\e',//two folder creation&nbsp; &nbsp; 'C:\\\\ab\\c',&nbsp; &nbsp; 'B:\\\\ab\\c',&nbsp; &nbsp; 'B:\\\\ab',//expect B\\\\ab\\c to be dropped]console.log(nodupes(archives))
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript