29e*_*9er 200 filter ecmascript-6
让我们说我有一个对象:
{
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
}
Run Code Online (Sandbox Code Playgroud)
我想通过过滤上面的对象来创建另一个对象,所以我有类似的东西.
{
item1: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种使用Es6实现这一目标的简洁方法,因此我可以使用扩展运算符.谢谢!
ssu*_*ube 386
如果您有允许值列表,则可以使用以下命令轻松地将它们保留在对象中:
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
const filtered = Object.keys(raw)
.filter(key => allowed.includes(key))
.reduce((obj, key) => {
obj[key] = raw[key];
return obj;
}, {});
console.log(filtered);Run Code Online (Sandbox Code Playgroud)
这用于:
Object.keys列出raw(原始数据)中的所有属性,然后Array.prototype.filter 使用选择允许列表中存在的键
Array.prototype.includes 确保他们在场Array.prototype.reduce 仅使用允许的属性构建新对象.这将使用允许的属性进行浅表复制(但不会复制属性本身).
您还可以使用对象扩展运算符来创建一系列对象而不会改变它们(感谢rjerue提到这一点):
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
const filtered = Object.keys(raw)
.filter(key => allowed.includes(key))
.reduce((obj, key) => {
return {
...obj,
[key]: raw[key]
};
}, {});
console.log(filtered);Run Code Online (Sandbox Code Playgroud)
出于琐事的目的,如果你想从原始数据中删除不需要的字段(我不建议这样做,因为它涉及一些丑陋的突变),你可以includes像这样反转检查:
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
Object.keys(raw)
.filter(key => !allowed.includes(key))
.forEach(key => delete raw[key]);
console.log(raw);Run Code Online (Sandbox Code Playgroud)
我将此示例包含在内,以显示基于突变的解决方案,但我不建议使用它.
Rya*_* H. 67
如果您是使用ES6语法OK,我发现,最干净的方式来做到这一点,因为注意到这里和这里是:
const data = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const { item2, ...newData } = data;
Run Code Online (Sandbox Code Playgroud)
现在,newData包含:
{
item1: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
Run Code Online (Sandbox Code Playgroud)
或者,如果您将密钥存储为字符串:
const key = 'item2';
const { [key]: _, ...newData } = data;
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,[key]转换为item2但由于您使用的是const赋值,因此需要为赋值指定名称._代表一个扔掉的价值.
更普遍:
const { item2, ...newData } = data; // Assign item2 to item2
const { item2: someVarName, ...newData } = data; // Assign item2 to someVarName
const { item2: _, ...newData } = data; // Assign item2 to _
const { ['item2']: _, ...newData } = data; // Convert string to key first, ...
Run Code Online (Sandbox Code Playgroud)
这不仅会减少您对单行的操作,而且还不需要您知道其他键是什么(您想要保留的那些键).
Guy*_*gev 38
最简单的方法是使用Lodash#pick
const _ = require('lodash');
const allowed = ['item1', 'item3'];
const obj = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
}
const filteredObj = _.pick(obj, allowed)
Run Code Online (Sandbox Code Playgroud)
小智 30
基于这两个答案:
/sf/answers/3925699361/
/sf/answers/3848369941/
我们可以做的:
const original = { a: 1, b: 2, c: 3 };
const allowed = ['a', 'b'];
const filtered = Object.fromEntries(allowed.map(k => [k, original[k]]));
Run Code Online (Sandbox Code Playgroud)
哪个更干净、更快:
https://jsbench.me/swkv2cbgkd/1
Cle*_*elm 18
没有什么是以前没有说过的,而是将一些答案与一般的ES6答案结合起来:
const raw = {
item1: { key: 'sdfd', value: 'sdfd' },
item2: { key: 'sdfd', value: 'sdfd' },
item3: { key: 'sdfd', value: 'sdfd' }
};
const filteredKeys = ['item1', 'item3'];
const filtered = filteredKeys
.reduce((obj, key) => ({ ...obj, [key]: raw[key] }), {});
console.log(filtered);Run Code Online (Sandbox Code Playgroud)
Nov*_*ovy 18
只是一行代码中的另一种解决方案.
我正在玩" 解构 "功能:
const raw = {
item1: { key: 'sdfd', value: 'sdfd' },
item2: { key: 'sdfd', value: 'sdfd' },
item3: { key: 'sdfd', value: 'sdfd' }
};
var myNewRaw = (({ item1, item3}) => ({ item1, item3 }))(raw);
console.log(myNewRaw);Run Code Online (Sandbox Code Playgroud)
您可以添加泛型ofilter(使用泛型实现oreduce),这样您就可以像使用数组一样轻松地过滤对象 -
const oreduce = (f, acc, o) =>
Object
.entries (o)
.reduce
( (acc, [ k, v ]) => f (acc, v, k, o)
, acc
)
const ofilter = (f, o) =>
oreduce
( (acc, v, k, o)=>
f (v, k, o)
? Object.assign (acc, {[k]: v})
: acc
, {}
, o
)
Run Code Online (Sandbox Code Playgroud)
我们可以看到它在这里工作 -
const data =
{ item1: { key: 'a', value: 1 }
, item2: { key: 'b', value: 2 }
, item3: { key: 'c', value: 3 }
}
console.log
( ofilter
( (v, k) => k !== 'item2'
, data
)
// [ { item1: { key: 'a', value: 1 } }
// , { item3: { key: 'c', value: 3 } }
// ]
, ofilter
( x => x.value === 3
, data
)
// [ { item3: { key: 'c', value: 3 } } ]
)
Run Code Online (Sandbox Code Playgroud)
在下面的浏览器中验证结果 -
const oreduce = (f, acc, o) =>
Object
.entries (o)
.reduce
( (acc, [ k, v ]) => f (acc, v, k, o)
, acc
)
const ofilter = (f, o) =>
oreduce
( (acc, v, k, o)=>
f (v, k, o)
? Object.assign (acc, { [k]: v })
: acc
, {}
, o
)
const data =
{ item1: { key: 'a', value: 1 }
, item2: { key: 'b', value: 2 }
, item3: { key: 'c', value: 3 }
}
console.log
( ofilter
( (v, k) => k !== 'item2'
, data
)
// [ { item1: { key: 'a', value: 1 } }
// , { item3: { key: 'c', value: 3 } }
// ]
, ofilter
( x => x.value === 3
, data
)
// [ { item3: { key: 'c', value: 3 } } ]
)Run Code Online (Sandbox Code Playgroud)
这两个功能可以通过多种方式实现.我选择附加到Array.prototype.reduce内部,oreduce但你可以轻松地从头开始编写
Array.reduce在允许的键上使用该方法的另一种解决方案:
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
const filtered = allowed.reduce((obj, key) => {
obj[key] = raw[key];
return obj
}, {})
console.log(filtered);
Run Code Online (Sandbox Code Playgroud)
特别是在较大的源对象(在本例中为原始对象)的情况下,这将是有意义的。不会使用源的所有条目执行迭代,而只会使用要过滤的键,因此更短/更快......
但我不得不说我也喜欢这个答案中的解决方案,它使用和:Object.fromEntries Array.filterArray.includes
Run Code Online (Sandbox Code Playgroud)const object = Object.fromEntries( Object.entries(raw).filter(([key, value]) => allowed.includes(key)) );
这是我最近做的事情:
const dummyObj = Object.assign({}, obj);
delete dummyObj[key];
const target = Object.assign({}, {...dummyObj});
Run Code Online (Sandbox Code Playgroud)
小智 7
现在,您可以使用Object.fromEntries方法(查看浏览器支持)来使其更短,更简单:
const raw = { item1: { prop:'1' }, item2: { prop:'2' }, item3: { prop:'3' } };
const allowed = ['item1', 'item3'];
const filtered = Object.fromEntries(
Object.entries(raw).filter(
([key, val])=>allowed.includes(key)
)
);
Run Code Online (Sandbox Code Playgroud)
阅读更多有关:Object.fromEntries
捎带ssube 的回答。
这是一个可重复使用的版本。
Object.filterByKey = function (obj, predicate) {
return Object.keys(obj)
.filter(key => predicate(key))
.reduce((out, key) => {
out[key] = obj[key];
return out;
}, {});
}
Run Code Online (Sandbox Code Playgroud)
调用它使用
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
var filtered = Object.filterByKey(raw, key =>
return allowed.includes(key));
});
console.log(filtered);
Run Code Online (Sandbox Code Playgroud)
ES6 箭头函数的美妙之处在于您不必将其allowed作为参数传入。
filter可以使用Object.entries()代替而不使用来实现更简单的解决方案Object.keys()
const raw = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const allowed = ['item1', 'item3'];
const filtered = Object.entries(raw).reduce((acc,elm)=>{
const [k,v] = elm
if (allowed.includes(k)) {
acc[k] = v
}
return acc
},{})
Run Code Online (Sandbox Code Playgroud)
好吧,这种单线呢
const raw = {
item1: { key: 'sdfd', value: 'sdfd' },
item2: { key: 'sdfd', value: 'sdfd' },
item3: { key: 'sdfd', value: 'sdfd' }
};
const filteredKeys = ['item1', 'item3'];
const filtered = Object.assign({}, ...filteredKeys.map(key=> ({[key]:raw[key]})));
Run Code Online (Sandbox Code Playgroud)
小智 6
简单的方法!去做这个。
const myData = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const{item1,item3}=myData
const result =({item1,item3})Run Code Online (Sandbox Code Playgroud)
此处的答案绝对合适,但它们有点慢,因为它们需要遍历对象中每个属性的白名单。对于大型数据集,以下解决方案要快得多,因为它仅循环遍历白名单一次:
const data = {
allowed1: 'blah',
allowed2: 'blah blah',
notAllowed: 'woah',
superSensitiveInfo: 'whooooah',
allowed3: 'bleh'
};
const whitelist = ['allowed1', 'allowed2', 'allowed3'];
function sanitize(data, whitelist) {
return whitelist.reduce(
(result, key) =>
data[key] !== undefined
? Object.assign(result, { [key]: data[key] })
: result,
{}
);
}
sanitize(data, whitelist)
Run Code Online (Sandbox Code Playgroud)
你可以这样做:
const base = {
item1: { key: 'sdfd', value:'sdfd' },
item2: { key: 'sdfd', value:'sdfd' },
item3: { key: 'sdfd', value:'sdfd' }
};
const filtered = (
source => {
with(source){
return {item1, item3}
}
}
)(base);
// one line
const filtered = (source => { with(source){ return {item1, item3} } })(base);
Run Code Online (Sandbox Code Playgroud)
这有效但不是很清楚,而且with不推荐使用该语句(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with)。
我知道这已经有很多答案,并且是一个相当古老的问题。但我刚刚想出了这样一句简洁的话:
JSON.parse(JSON.stringify(raw, ['key', 'value', 'item1', 'item3']))
Run Code Online (Sandbox Code Playgroud)
这将返回另一个仅包含白名单属性的对象。请注意,key和value包含在列表中。