首页 > 解决方案 > 从 URL 创建对象树

问题描述

我有一个这样的 URL 数组:

const urls = [
  'src/components/index.js',
  'src/components/style.css',
  'readme.txt',
  'photos/something/somwhere/why.jpg',
  'places/something/home,
];

我想有这样的输出:

{
  'src': {
    'components': {
      'index.js': true,
      'style.css': true
    }
  },
  
  'readme.txt': true,
    
  'photos': {
    'something': {
      'somewhere': {
        'why.jpg'
      }
      'home': {}
    }
    
  }

最后的文件应该有值 true 并且空文件夹应该有一个空对象作为值。

到目前为止,我尝试使用嵌套循环来做到这一点,但它总是失败。到目前为止,我最好的选择就是这个,但它并不完整。

const result = {};

const urls = [
  'src/components/index.js',
  'src/components/style.css',
  'readme.txt',
  'photos/something/somwhere/why.jpg',
  'places/something/home',
];

const urlArr = [];

urls.forEach(url => {
  const items = url.split('/');
  urlArr.push(items);
});

for (let i = 0; i < urlArr.length; i++) {
  for (let j = 0; j < urlArr[i].length; j++) {
    let item = urlArr[i][j];

  }
}


console.log(urlArr);

如果可以使用外部方式,那也很棒(比如递归或其他东西)。

标签: javascriptstringloopsobjectrecursion

解决方案


你可以通过很多不同的方式做到这一点,但这就是我的做法。 H&T代表Head&Tail并且是设计对列表进行操作的递归函数时的标准名称。

const urls = [
  'src/components/index.js',
  'src/components/style.css',
  'readme.txt',
  'photos/something/somwhere/why.jpg',
  'places/something/home',
];

const recursiveAssign = ([H, ...T], target) => {
  if (H.indexOf('.') !== -1) {
    target[H] = true;
    return;
  }
  
  target[H] = target[H] || {};
  if (T.length > 0) recursiveAssign(T, target[H]);
}

const createTree = (paths) => {
  const acc = {};
  for (let path of paths) {
    recursiveAssign(path.split('/'), acc);
  }
  return acc;
}

console.log(createTree(urls));

或者,如果您更喜欢用一种不太冗长的方式来编写相同的解决方案。

const urls = [
  'src/components/index.js',
  'src/components/style.css',
  'readme.txt',
  'photos/something/somwhere/why.jpg',
  'places/something/home',
]

const recursiveAssign = ([H, ...T], target) =>
  H.indexOf('.') !== -1
    ? target[H] = true
    : T.length > 0
      ? recursiveAssign(T, target[H] = target[H] || {})
      : target[H] = {}

const createTree = ([H, ...T], acc = {}) => (
  recursiveAssign(H.split('/'), acc),
  T.length > 0
    ? createTree(T, acc)
    : acc
)

console.log(createTree(urls))


推荐阅读