在多维数组上应用过滤器,并返回过滤的数据以及父对象

时间:2019-02-05 03:04:41

标签: javascript arrays dictionary filter ecmascript-6

我具有代码片段中提供的多维数组,我想用最里面的数组的值过滤该数组,然后将该值与parent一起返回。 例如

来自

const nodes = [
    {
        value: 'Documents',
        label: 'Documents',
        children: [
            {
                value: 'Employee Evaluations.zip',
                label: 'Employee Evaluations.zip',
            },
            {
                value: 'Expense Report.pdf',
                label: 'Expense Report.pdf',
            },
            {
                value: 'notes.txt',
                label: 'notes.txt',
            },
        ],
    },
    {
        value: 'Photos',
        label: 'Photos',
        children: [
            {
                value: 'nyan-cat.gif',
                label: 'nyan-cat.gif',
            },
            {
                value: 'SpaceX Falcon9 liftoff.jpg',
                label: 'SpaceX Falcon9 liftoff.jpg',

            },
        ],
    },
]; 

如果我通过“ notes.txt”进行过滤,则应该产生

 [
    {
        value: 'Documents',
        label: 'Documents',
        children: [

            {
                value: 'notes.txt',
                label: 'notes.txt',
            }
        ]
]

这是我尝试过的方法,但它只返回最里面的已过滤内容

const nodes = [
    {
        value: 'Documents',
        label: 'Documents',
        children: [
            {
                value: 'Employee Evaluations.zip',
                label: 'Employee Evaluations.zip',
            },
            {
                value: 'Expense Report.pdf',
                label: 'Expense Report.pdf',
            },
            {
                value: 'notes.txt',
                label: 'notes.txt',
            },
        ],
    },
    {
        value: 'Photos',
        label: 'Photos',
        children: [
            {
                value: 'nyan-cat.gif',
                label: 'nyan-cat.gif',
            },
            {
                value: 'SpaceX Falcon9 liftoff.jpg',
                label: 'SpaceX Falcon9 liftoff.jpg',
               
            },
        ],
    },
];
let key="notes.txt";
//let filtered=nodes.filter(n=>n.value===key);
let cfiltered=nodes.map(n=>n.children.filter(n1=>n1.value===key));
//console.log(filtered);
console.log(cfiltered);

3 个答案:

答案 0 :(得分:2)

首先,在所有mapparent并过滤出不匹配的子项,然后根据children的大小过滤中间结果。

const nodes = [{
    value: 'Documents',
    label: 'Documents',
    children: [{
        value: 'Employee Evaluations.zip',
        label: 'Employee Evaluations.zip',
      },
      {
        value: 'Expense Report.pdf',
        label: 'Expense Report.pdf',
      },
      {
        value: 'notes.txt',
        label: 'notes.txt',
      },
    ],
  },
  {
    value: 'Photos',
    label: 'Photos',
    children: [{
        value: 'nyan-cat.gif',
        label: 'nyan-cat.gif',
      },
      {
        value: 'SpaceX Falcon9 liftoff.jpg',
        label: 'SpaceX Falcon9 liftoff.jpg',

      },
    ],
  },
];
let key="notes.txt";
const result = nodes.map(node => ({ ...node,
  children: node.children.filter(child => child.value === key)
})).filter(node => node.children.length);
console.log(result);

希望这会有所帮助!

答案 1 :(得分:0)

我的头顶上完全没有经过测试,但想法是:

  • 过滤至少有一个孩子的节点。值==键
  • 过滤每个结果节点的子节点:

它会像这样:

nodes.filter(n => n.children.reduce((cur, acc) => acc || cur.value == key, false).length > 0)
     .map(n => Object.assign(n, { children: n.children.filter(c => c.value == key }))

也许吗?

[编辑]添加了一个初始值以减少

[编辑]添加了Object.assign,因此您也可以获取原始对象。我真的应该先测试它;)但是您掌握了原理!

答案 2 :(得分:0)

我怀疑您的尺寸可能大于两个。您想将此视为树状问题。由于您关心父母和孩子,因此可以使用深度优先搜索。

function getNodeWithChild( accumulator, rootNode, searchValue ) {
  if (!rootNode || !rootNode.children) return accumulator;

  let parentNode;
  rootNode.children.forEach( child => {
     accumulator = getNodeWithChild(accumulator, child, searchValue);
     if (child.value === searchValue || child.label === searchValue) {
       if (parentNode) {
          parentNode.children.push(child);
       } else {
         parentNode = Object.assign({}, rootNode);
         parentNode.children = [child];
       }
    }
    if (parentNode) {
      accumulator.push(parentNode);
    }
  }
  return accumulator
} 

// And you call it like this:
const tree = { children: nodes } // just to simplify treat it like the same node as the rest
const filteredNodes = getNodeWithChild( [], rootNode, 'notes.txt'); 

这是递归版本,但可以与队列进行迭代。它未经测试,可能会使用一些调试功能。但是它应该返回每个孩子的parentNode的值。如果父母和孩子都包含该值,则它将同时返回。它将删除所有不具有该值的子项。