过滤器数组以递归方式查找父项

时间:2016-10-12 18:17:19

标签: javascript arrays algorithm filter lodash

我有一个这样的数组:

[
    {"id":"one","name":"school", "selected": false, "children":[
      {"id":"1","name":"school", "selected": false},
      {"id":"2","name":"student", "selected": true},
      {"id":"3","name":"teacher", "selected": false}
      ]},
      {"name":"two","name":"school", "selected": false, "children":[
      {"id":"1","name":"school", "selected": true},
      {"id":"3","name":"teacher", "selected": false}
      ]},
      {"name":"three","name":"school", "selected": true, "children":[
      {"id":"1","name":"school", "selected": false},
      {"id":"2","name":"student", "selected": false}
      ]}
  ]

如何过滤该数组以仅获取将字段选为true的对象的名称?

输出应该是对象名称的数组:

[student, school, school]

我用lodash尝试了这个:

_.filter(array, {selected: true}).map(function (division) {
            return array.name;
        });

但是这总是返回根对象,而不是子对象内的对象。

7 个答案:

答案 0 :(得分:3)

您可以迭代并查看所需属性selected是否为true,如果有子项则推送到结果,迭代子项。

这适用于Array#forEach

var data = [{ "id": "one", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "two", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "three", "name": "school", "selected": true, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": false }] }],
    result = [];

data.forEach(function iter(o) {
    o.selected && result.push(o.name);
    (o.children || []).forEach(iter);
});
  
console.log(result);

与lodash _.forEach

相同

var data = [{ "id": "one", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "two", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "three", "name": "school", "selected": true, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": false }] }],
    result = [];

_.forEach(data, function iter(o) {
    o.selected && result.push(o.name);
    _.forEach(o.children, iter);
});
  
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

Array#reduce的版本。

var data = [{ "id": "one", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "two", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "three", "name": "school", "selected": true, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": false }] }],
    result = data.reduce(function iter(r, o) {
        o.selected && r.push(o.name);
        return (o.children || []).reduce(iter, r);
    }, []);
  
console.log(result);

另一个版本是lodash _.reduce

var data = [{ "id": "one", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "two", "name": "school", "selected": false, "children": [{ "id": "1", "name": "school", "selected": true }, { "id": "3", "name": "teacher", "selected": false }] }, { "name": "three", "name": "school", "selected": true, "children": [{ "id": "1", "name": "school", "selected": false }, { "id": "2", "name": "student", "selected": false }] }],
    result = _.reduce(data, function iter(r, o) {
        o.selected && r.push(o.name);
        return _.reduce(o.children, iter, r);
    }, []);
  
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

答案 1 :(得分:1)

array
   .reduce((a, i) => [...a, i, ...i.childs], [])//flatten array
   .filter(i => i.selected)//filter with selected===true
   .map(i => i.name));//map to name

console.log([{
  "id": "one",
  "name": "school",
  "selected": false,
  "childs": [{
    "id": "1",
    "name": "school",
    "selected": false
  }, {
    "id": "2",
    "name": "student",
    "selected": true
  }, {
    "id": "3",
    "name": "teacher",
    "selected": false
  }]
}, {
  "name": "two",
  "name": "school",
  "selected": false,
  "childs": [{
    "id": "1",
    "name": "school",
    "selected": true
  }, {
    "id": "3",
    "name": "teacher",
    "selected": false
  }]
}, {
  "name": "three",
  "name": "school",
  "selected": true,
  "childs": [{
    "id": "1",
    "name": "school",
    "selected": false
  }, {
    "id": "2",
    "name": "student",
    "selected": false
  }]
}].reduce((a, i) => [...a, i, ...i.childs], []).filter(i => i.selected).map(i => i.name));

答案 2 :(得分:1)

您可以使用此函数式编程样式的ES6解决方案:

function sel(array) {
    return (array || []).reduce ( (acc, o) => 
        (o.selected ? acc.concat(o.name) : acc).concat(sel(o.childs)), [] );
}

&#13;
&#13;
  
function sel(array) {
    return (array || []).reduce ( (acc, o) => 
        (o.selected ? acc.concat(o.name) : acc).concat(sel(o.childs)), [] );
}
// Sample data
var array = [
    {"id":"one","name":"school", "selected": false, "childs":[
      {"id":"1","name":"school", "selected": false},
      {"id":"2","name":"student", "selected": true},
      {"id":"3","name":"teacher", "selected": false}
      ]},
      {"name":"two","name":"school", "selected": false, "childs":[
      {"id":"1","name":"school", "selected": true},
      {"id":"3","name":"teacher", "selected": false}
      ]},
      {"name":"three","name":"school", "selected": true, "childs":[
      {"id":"1","name":"school", "selected": false},
      {"id":"2","name":"student", "selected": false}
      ]}
  ];
// Extract
var result = sel(array);
// Ooutput result
console.log(result);
&#13;
&#13;
&#13;

答案 3 :(得分:1)

您可以使用Array.prototype.map()Array.prototype.filter()

&#13;
&#13;
var arr = [{
  "id": "one",
  "name": "school",
  "selected": false,
  "childs": [{
    "id": "1",
    "name": "school",
    "selected": false
  }, {
    "id": "2",
    "name": "student",
    "selected": true
  }, {
    "id": "3",
    "name": "teacher",
    "selected": false
  }]
}, {
  "name": "two",
  "name": "school",
  "selected": false,
  "childs": [{
    "id": "1",
    "name": "school",
    "selected": true
  }, {
    "id": "3",
    "name": "teacher",
    "selected": false
  }]
}, {
  "name": "three",
  "name": "school",
  "selected": true,
  "childs": [{
    "id": "1",
    "name": "school",
    "selected": false
  }, {
    "id": "2",
    "name": "student",
    "selected": false
  }]
}];

var res = arr.map(el =>
  (el.selected && el || el.childs.filter(child =>
    child.selected
  )[0]).name
);

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

答案 4 :(得分:0)

那么,您应该考虑您尝试构建的脚本的复杂性。这是一个嵌套的线性算法(参见https://en.wikipedia.org/wiki/Linear_search),因为您必须触摸数组中的每个元素以创建具有selected元素的新数据结构,如果该数组大小增加,这可能会非常慢

您可能想要做的是修改切换selected属性的方法,并将该“选定”对象复制到新的selectedElements数组。

但是,如果您需要按照自己的要求进行操作,并且只需要独特的结果,请查看以下内容:

var data = [
  {"id":"one","name":"school", "selected": false, "childs":[
    {"id":"1","name":"school", "selected": false},
    {"id":"2","name":"student", "selected": true},
    {"id":"3","name":"teacher", "selected": false}
  ]},
  {"name":"two","name":"school", "selected": false, "childs":[
    {"id":"1","name":"school", "selected": true},
    {"id":"3","name":"teacher", "selected": false}
  ]},
  {"name":"three","name":"school", "selected": true, "childs":[
    {"id":"1","name":"school", "selected": false},
    {"id":"2","name":"student", "selected": false}
  ]}
],
    selectedElements = [];

data.map(function(row, i){
  if (row.selected) {
    if (selectedElements.indexOf(row.name) == - 1)
      selectedElements.push(row.name);
  }
  else{
    row.childs.map(function(childRow, ii) {
      if (childRow.selected) {
        if (selectedElements.indexOf(childRow.name) == - 1)
          selectedElements.push(childRow.name);
        }
    })
  }
});

console.log(selectedElements);

答案 5 :(得分:0)

在你的lodash _.filter

之前添加一行
array = _.flatten(array.map(x => [x].concat(x.childs)))

所以需要childs

答案 6 :(得分:0)

带箭头功能的经典递归解决方案

var result = [];
var recursiveSearch = arr => {
  if (Array.isArray(arr)) {
    arr.forEach(x => {
    if (x.selected === true) result.push(x.name);
    if (Array.isArray(x.childs)) recursiveSearch(x.childs);
    });
  }
}
recursiveSearch(data);
console.log (result);