如何创建文件夹结构的嵌套对象表示

时间:2017-06-26 12:28:31

标签: arrays node.js object recursion

所以我需要一个平面数组和一个嵌套对象来表示文件夹结构。但是,它需要过滤掉内部没有某些文件(FILE.txt)的某些文件夹,并忽略所有文件。

考虑这些文件:

.
├── folder0                # not this folder
│   ├── FILE.txt           # <- here  
│   ├── some.other
│   └── more.files
├── stuff                  # not this folder
│   ├── some.other
│   └── more.files
└── folder1
    ├── FILE.txt           # <- here
    ├── subfolder1
    │   ├── FILE.txt       # <- here
    │   ├── some.other
    │   └── more.files
    ├── subfolder2
    │   └── FILE.txt       # <- here
    └── subfolder3
        ├── FILE.txt       # <- here
        ├── subsubfolder1
        │   ├── FILE.txt   # <- here
        │   ├── some.other
        │   └── more.files
        └── subsubfolder2
            └── FILE.txt   # <- here

我需要的是两件事:

一个平面数组,其中包含指向其中FILE.txt的每个文件夹的路径:

[
  "folder0",
  "folder1",
  "folder1/subfolder1",
  "folder1/subfolder2",
  "folder1/subfolder3",
  "folder1/subfolder3/subsubfolder1",
  "folder1/subfolder3/subsubfolder1"
]

一个嵌套对象,代表文件夹的嵌套:

{
  'folder0': 'folder0',
  'folder1': {
    'subfolder1': 'subfolder1',
    'subfolder2': 'subfolder2',
    'subfolder3': {
      'subsubfolder1': 'subsubfolder1',
      'subsubfolder2': 'subsubfolder2'
    }
  }
}

现在我得到了第一个。非常简单的递归遍历系统:

const GetContent = ( folder, content = []) => {
  if( Fs.existsSync( folder ) ) {
    Fs.readdirSync( folder )
      .map(
        file => {
          if( Fs.statSync( Path.join( folder, file ) ).isDirectory() ) {
            const result = GetContent( Path.join( folder, file ), content );
            content = [ ...result ];
          }
          else {
            if( file === `${ SETTINGS.get().folder.index }.yml` ) {
              content.push( folder );
            }
          }
        }
      );

    return content;
  }
};

此代码将为我提供平面阵列,一切都很好。

问题

  • 但是如何找到我的嵌套对象?我想阻止两次访问文件系统。
  • 这应该作为一个额外的功能完成,还是与上面相同,以防止又一个循环?

我尝试了什么

我已经试过太长时间以某种方式将它放在同一个函数中。 然后我想也许我只是将平面阵列转换为嵌套对象,但今天我的头疼了。但是下面的破坏测试不会这样做。我想今天我的头被阻挡了。有人帮忙吗?

const ToDepth = ( items, result, iterator = 0 ) => {

  iterator ++;
  result[ items[ 0 ] ] = {};

  if( items.length > 1 ) {
    result[ items[ 0 ] ] = ToDepth( items.slice( 1 ), result[ items[ 0 ] ], iterator );
  }
  else {
    if( Object.keys( result[ items[ 0 ] ] ).length === 0 ) {
      result[ items[ 0 ] ] = items[ 0 ];
    }
  }

  return result;
}


const ToNested = ( element ) => {
  let result = {};

  element.map( ( item ) => {
    result = ToDepth( item.split('/'), result );
  });

  return result;
};

ToNested( flatArray );

1 个答案:

答案 0 :(得分:2)

这是我对代码的看法:

&#13;
&#13;
const flat = [
  "folder0",
  "folder1",
  "folder1/subfolder1",
  "folder1/subfolder2",
  "folder1/subfolder3",
  "folder1/subfolder3/subsubfolder1",
  "folder1/subfolder3/subsubfolder2"
];
const nested = {};
const add = (source, target) => {
  const elements = source.split("/");
  const element = elements.shift();
  target[element] = target[element] || element;
  if (elements.length) {
    target[element] = typeof target[element] === "object" ? target[element] : {};
    add(elements.join("/"), target[element]);
  }
};

flat.forEach(item => add(item, nested));

console.log(nested);
&#13;
&#13;
&#13;

基本上,它是一个递归函数,它将平面数组中每个元素的连续部分添加到目标对象,根据需要向下移动结构。你可能会让这更漂亮。但它可以工作并输出你想要的东西。