如何在ES6中按其值过滤对象

23

ES6中过滤对象的最佳方法是什么?

起始数据:

const acceptedValues = ["value1", "value3"]
const myObject = {
    prop1: "value1",
    prop2: "value2",
    prop3: "value3"
}

期望输出:

filteredObject = {
    prop1: "value1",
    prop3: "value3"
}

2
最好的方式是指什么?简单地循环遍历对象的属性即可。 - Felix Kling
如果可能的话,尽量捕获接受的键而不是值,以使此过程更加简单。 - hazardous
就效率而言,一个简单的循环确实可以解决问题。但是ES6和“现代”数组方法可以使它更容易。在我看来,使用.reduce()的答案就是一个不错的例子。 - saawsann
最好的方法?从一开始就不要使用 Object(而应该使用 Array)。 - user6445533
9个回答

23

您可以使用reduce()创建新的对象,并使用includes()检查数组中是否存在对象的值。

const acceptedValues = ["value1", "value3"]
const myObject = {
  prop1: "value1",
  prop2: "value2",
  prop3: "value3"
}

var filteredObject = Object.keys(myObject).reduce(function(r, e) {
  if (acceptedValues.includes(myObject[e])) r[e] = myObject[e]
  return r;
}, {})

console.log(filteredObject)


请问为什么在这种情况下使用.filter不起作用,当我有一个对象时? this.activeUsers = window.users.filter( function(user) {// return ( (user.test === '0') && (user.isok === '0') ); return user.user_id === 1; }); 出现错误.filter is not a function - Imnotapotato
1
@W.Doch 因为过滤器只适用于数组,而不适用于对象。 - Emobe

11

对于ES6和if

  • 如果您的任务只需要基于键进行过滤即可解决,
  • 您需要静态代码(您确切地知道要过滤哪些属性),
  • 并且它不依赖于应用程序状态,

那么您可以使用以下解构技术:

const myObject = {
  prop1: 'value1',
  prop2: 'value2',
  prop3: 'value3'
}
const { prop2, ...filteredObject } = myObject

console.info({ filteredObject, prop2 })

然后你将会拥有:

filteredObject: {prop1: "value1", prop3: "value3"}
prop2: "value2"

3
这是基于关键字不匹配进行过滤,而问题是要根据值匹配进行过滤。 - billkw

6

为了进一步完善@Nenad Vracar的好答案,你可以使用对象而不是数组,并使用includes进行更快的查找:

const acceptedValues = ["value1", "value3"];
const myObject = {
  prop1: "value1",
  prop2: "value2",
  prop3: "value3"
};

const lookup = acceptedValues.reduce( (memo, prop) => {
  memo[prop] = true;
  return memo;
});

const filteredObject = Object.keys(myObject).reduce((filtered, key) => {
  if(lookup[myObject[key]]){
    filtered[key] = myObject[key];
  }
  return filtered;
}, {});

console.log(filteredObject);

不是说 includes 不能胜任这个工作,但我想提供一种替代方案。


6

鉴于我在这里没有看到使用Object.entries的答案,这里提供一份。请注意,由于Object.entries()的实现比Object.keys()慢得多,因此这种方法的速度也会比被接受的答案慢,但有些人可能更喜欢这种方法,因为它更易读或可扩展(更容易传递不同的过滤函数)。

const acceptedValues = ["value1", "value3"];
const myObject = {
    prop1:"value1",
    prop2:"value2",
    prop3:"value3"
};
const filteredEntries = Object.entries(myObject).filter(([, v]) => acceptedValues.includes(v));
const filteredObject = Object.fromEntries(filteredEntries);

作为一行较长的命令:

或者作为一行比较长的命令:

const filteredObject = Object.fromEntries(Object.entries(myObject).filter(([, v]) => accepted.includes(v)));

那就是我正在寻找的!我知道 Object.entries 是正确的方法。要注意它慢一些(但在大多数情况下这很少成问题)。 - Tom Auger
类型错误,Object.fromEntries 不是一个函数。 - Aaron
你使用的是什么浏览器?应该在所有现代浏览器上都支持:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries#browser_compatibility - naktinis
谢谢你提供的fromEntries建议,很不错。 - undefined

4
为什么不使用简单的for循环?

const acceptedValues = ["value1","value3"]
const myObject = {
    prop1:"value1",
    prop2:"value2",
    prop3:"value3"
};
var  filteredObject = {};
for(e in myObject) {
    if (myObject.hasOwnProperty(e)) {
      if (acceptedValues.indexOf(myObject[e]) != -1) {
          filteredObject[e] = myObject[e];
      }
    }
}
console.log(filteredObject);


1
至少那时候用个发电机哈哈 - undefined

0

刚刚看了你的一个视频.. Fireship 真是太棒了! - dragi
3
这是按键过滤的内容,不是问题所要求的。 - billkw

0
使用简单的for循环和按键获取对象。

const acceptedValues = ["value1","value3"]
const myObject = {
    prop1:"value1",
    prop2:"value2",
    prop3:"value3"
}

Object.prototype.getKeyByValue = function( value ) {
    for( var prop in this ) {
        if( this.hasOwnProperty( prop ) ) {
             if( this[ prop ] === value )
                 return prop;
        }
    }
}

for (var i in acceptedValues) {
  if (myObject.getKeyByValue(acceptedValues[i])){
    console.log(acceptedValues[i]);
  }
}


一般来说,不建议更改原型的原因有很多。 - undefined

0
function filter(myObject){
  var obj=Object.assign({},myObject);
  Object.keys(obj).forEach(function(key) {
      if(acceptedValues.indexOf(obj[key])<0) delete obj[key];
  });
  return obj;
}
const filteredObject=filter(myObject);

0
const newObj = {};
for(let key of Object.keys(myObject)){
  if(acceptedValues.includes(key)){
    newObj[key] = myObject[key]
  }
}
console.log(newObj);

2
我建议您不要仅仅发布代码作为答案,还应该提供解释您的代码是如何解决问题的。带有解释的答案通常更有帮助和更高质量,并且更有可能吸引赞同。 - Mark Rotteveel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接