javascript - Flatten multi-level folder tree structure leaving only 'file'-type items in the output - Stack Over

I have an array like below in which there are two types of data, file or folder. I only want to filter

I have an array like below in which there are two types of data, file or folder. I only want to filter file type data.

let data = [
    {
      "id": 3,
      "type": "file",
      "url": "www.first"
    }, {
      "id": 4,
      "type": "file",
      "url": "www.second"
    }, {
      "id": 5,
      "type": "folder",
      "items": [
          {
            "id": 6,
            "type": "file",
            "url": "www.third"
          }
       ]
    }
];

Desired result is

[
    {
        "id": 3,
        "type": "file",
        "url": "www.first"
    }, {
        "id": 4,
        "type": "file",
        "url": "www.second"
    }, {
        "id": 6,
        "type": "file",
        "url": "www.third"
    }
]

NOTE: There can be multiple levels like inside folder items, there can be another folder

Any help would be appreciated. Thanks!

I have an array like below in which there are two types of data, file or folder. I only want to filter file type data.

let data = [
    {
      "id": 3,
      "type": "file",
      "url": "www.first."
    }, {
      "id": 4,
      "type": "file",
      "url": "www.second."
    }, {
      "id": 5,
      "type": "folder",
      "items": [
          {
            "id": 6,
            "type": "file",
            "url": "www.third."
          }
       ]
    }
];

Desired result is

[
    {
        "id": 3,
        "type": "file",
        "url": "www.first."
    }, {
        "id": 4,
        "type": "file",
        "url": "www.second."
    }, {
        "id": 6,
        "type": "file",
        "url": "www.third."
    }
]

NOTE: There can be multiple levels like inside folder items, there can be another folder

Any help would be appreciated. Thanks!

Share Improve this question edited Jun 16, 2020 at 9:12 Yevhen Horbunkov 15.6k3 gold badges27 silver badges45 bronze badges asked Jun 16, 2020 at 8:32 Sagar JajoriyaSagar Jajoriya 2,3751 gold badge12 silver badges17 bronze badges 0
Add a ment  | 

5 Answers 5

Reset to default 5

Assuming your folder structure may span few levels deep, you may need to traverse your input array recursively to flatten the tree structure, Array.prototype.flatMap() may e in handy for that:

const src = [
    {
      "id": 3,
      "type": "file",
      "url": "www.first."
    }, {
      "id": 4,
      "type": "file",
      "url": "www.second."
    }, {
      "id": 5,
      "type": "folder",
      "items": [
          {
            "id": 6,
            "type": "folder",
            "items" : [
              {
                "id" : 7,
                "type" : "file",
                "ulr" : "www.third."
              }
            ]
          }
       ]
    }
],

    flattenArr = arr => 
      arr.flatMap(({items=[], ...rest}) => 
        rest.type == 'folder' ? flattenArr(items) : rest)
      
      
console.log(flattenArr(src))
.as-console-wrapper {min-height:100%;}

Recursive function that will traverse items if it exists. Returns all files and flattens the arrays using flatMap. Ignores all other types.

let data = [
    {
      "id": 3,
      "type": "file",
      "url": "www.first."
    }, {
      "id": 4,
      "type": "file",
      "url": "www.second."
    }, {
      "id": 5,
      "type": "folder",
      "items": [
          {
            "id": 6,
            "type": "file",
            "url": "www.third."
          }
       ]
    }
];
walk = node =>
  node.type === 'file' ? node : (node.items||[]).flatMap(walk)

console.log(data.flatMap(walk))

you can use .flatMap() along with .filter() function to do this.

P.S. This solution will work only 1 level deep, i.e. if you have file type objects inside a folder. See the edited part of the answer for the solution that will filter file type objects from nested folders inside folders.

let data = [
    { "id": 3, "type": "file", "url": "www.first." }, 
    { "id": 4, "type": "file", "url": "www.second." },
    {
      "id": 5,
      "type": "folder",
      "items": [
          { "id": 6, "type": "file", "url": "www.third." }
       ]
    }
];

const output = data.flatMap(a => {
  return a.type === 'file' 
          ? a
          : a.items.filter(item => item.type === 'file');  
});

console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }

EDIT:

Here's a recursive solution that will filter objects of type files from nested folders

let data = [
    { "id": 3, "type": "file", "url": "www.first." }, 
    { "id": 4, "type": "file", "url": "www.second." },
    {
      "id": 5,
      "type": "folder",
      "items": [
          { "id": 6, "type": "file", "url": "www.third." },
          {
            "id": 7,
            "type": "folder",
            "items": [
               { "id": 8, "type": "file", "url": "www.fourth." },
               {
                 "id": 9,
                 "type": "folder",
                 "items": [
                   { "id": 10, "type": "file", "url": "www.fifth." }
                 ]
              }
            ]
          }
       ]
    }
];

function filterFiles(arr) {
  return arr.flatMap(item => item.type === 'file' ? item : filterFiles(item.items));
}

console.log(filterFiles(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Use basic implementation of going through nested arrays.

Accumulate objects into the list if the object with type file is found.

let data = [{
  "id": 3,
  "type": "file",
  "url": "www.first."
}, {
  "id": 4,
  "type": "file",
  "url": "www.second."
}, {
  "id": 5,
  "type": "folder",
  "items": [{
    "id": 6,
    "type": "file",
    "url": "www.third."
  }]
}];


function recursive(arr) {
  const list = []
  for (let i = 0; i < data.length; i++) {
    if (arr[i] && arr[i].items && Array.isArray(arr[i].items)) {
      return [...list, ...recursive(arr[i].items)];
    }
    if (arr[i] && arr[i].type === 'file') {
      list.push(arr[i]);
    }
  }
  return list;

}

console.log(recursive(data))

data.filter(each => each.type === "file");

That will give you what you want

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745436051a4627613.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信