有没有更有效的方法来过滤此对象数组?

时间:2018-07-25 20:53:43

标签: javascript arrays filter

我正在处理此对象数组,并尝试根据匹配的主题对其进行过滤和重新排序。数组看起来像这样:

const results = [
  {id: 1, subject: 'biology', grade: 10},
  {id: 2, subject: 'biology', grade: 3},
  {id: 3, subject: 'math', grade: 4},
  {id: 4, subject: 'biology', grade: 2},
  {id: 5, subject: 'geography', grade: 1},
  {id: 6, subject: 'physics', grade: 3}
]

将来可能会增加更多的主题。 通过过多的过滤方法,我可以按照自己的方式排列它们:

var filteredObj = {};

filteredObj['biology'] = this.results.filter(function (result) {
    return result.subject === 'biology';
});
filteredObj['math'] = this.results.filter(function (result) {
    return result.subject === 'math';
});
filteredObj['physics'] = this.results.filter(function (result) {
    return result.subject === 'physics';
});
filteredObj['geography'] = this.results.filter(function (result) {
    return result.subject === 'geography';
});

有没有一种更有效的方法?

3 个答案:

答案 0 :(得分:5)

您可以使用Array.reduce()按主题对项目进行分组:

const results = [{"id":1,"subject":"biology","grade":10},{"id":2,"subject":"biology","grade":3},{"id":3,"subject":"math","grade":4},{"id":4,"subject":"biology","grade":2},{"id":5,"subject":"geography","grade":1},{"id":6,"subject":"physics","grade":3}];

const grouped = results.reduce((r, o) => {
  r[o.subject] = r[o.subject] || [];
  
  r[o.subject].push(o);

  return r;
}, Object.create(null));

console.log(grouped);

创建更通用的groupBy函数很容易:

const groupBy = (prop, arr) => arr.reduce((r, o) => {
  r[o[prop]] = r[o[prop]] || [];
  
  r[o[prop]].push(o);

  return r;
}, Object.create(null));

const results = [{"id":1,"subject":"biology","grade":10},{"id":2,"subject":"biology","grade":3},{"id":3,"subject":"math","grade":4},{"id":4,"subject":"biology","grade":2},{"id":5,"subject":"geography","grade":1},{"id":6,"subject":"physics","grade":3}];

const grouped = groupBy('subject', results);

console.log(grouped);

答案 1 :(得分:3)

尝试减少:

const results = [
  {id: 1, subject: 'biology', grade: 10},
  {id: 2, subject: 'biology', grade: 3},
  {id: 3, subject: 'math', grade: 4},
  {id: 4, subject: 'biology', grade: 2},
  {id: 5, subject: 'geography', grade: 1},
  {id: 6, subject: 'physics', grade: 3}
];

const filteredArray = results.reduce((obj, item) => {
  if (typeof obj[item.subject] === 'undefined') {
    obj[item.subject] = [item];
  } else {
    obj[item.subject].push(item);
  }
  
  return obj;
}, {});

console.log(filteredArray);

带有精美的es6 maps

const results = [
  {id: 1, subject: 'biology', grade: 10},
  {id: 2, subject: 'biology', grade: 3},
  {id: 3, subject: 'math', grade: 4},
  {id: 4, subject: 'biology', grade: 2},
  {id: 5, subject: 'geography', grade: 1},
  {id: 6, subject: 'physics', grade: 3}
];

const filteredArray = results.reduce((obj, item) => {
  const val = obj.get(item.subject) || [];
  
  val.push(item);
  obj.set(item.subject, val);
  
  return obj;
}, new Map());

for (const [subj, val] of filteredArray) {
  console.log(subj, val.length);
}
// console.log(JSON.stringify([...filteredArray]));

答案 2 :(得分:1)

使用.map()根据其属性之一对对象数组进行分组:

const results = [{ id: 1, subject: 'biology', grade: 10 },
    { id: 2, subject: 'biology', grade: 3 },
    { id: 3, subject: 'math', grade: 4 },
    { id: 4, subject: 'biology', grade: 2 },
    { id: 5, subject: 'geography', grade: 1 },
    { id: 6, subject: 'physics', grade: 3 }
];

var filtered = {};
results.map((o, i) => {
    if (!(o.subject in filtered)) filtered[o.subject] = [];   
    filtered[o.subject].push(results[i]);
});

console.log(filtered)

在这种情况下,我更喜欢这种方式,而不是.reduce(),因为概念更简洁,如果属性不存在,我们在新对象中创建它,如果已经在新对象中创建,我们添加元素。