let obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
}
let ids = [1, 2]
我想基于ids过滤obj。
我想要的结果是
{david:{id:1},约翰:{id:2}}
因为上面的ids是[1,2]。
我想用Ramda.js做这件事。
请帮我。
好吧,我很抱歉。
我做了这样的事。
let obj2 = {}
ids.forEach((x) => {
obj2 += R.filter(y => y.id === x, obj)
})
obj = obj2
但是,这是不正确的。
而且我不想使用forEach。
我想和Ramda.js一起做。
你只能使用Javascript
来做到这一点,首先你可以用你想要保留的ids
创建一个集合(检查set是否有一个元素是O(1)
)。然后,你可以循环原始object
并将key
与他的value
添加到新的object
上,如果该集合具有相关的id
:
let obj = {
tom: {id: 0},
david: {id: 1},
john: {id: 2}
}
let ids = [1, 2];
const filterByIds = (obj, ids) =>
{
let idsSet = new Set(ids);
let filteredObj = {};
for (k in obj)
{
if (idsSet.has(obj[k].id))
filteredObj[k] = obj[k];
}
return filteredObj;
}
console.log(filterByIds(obj, ids));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
使用Ramda你可以这样做:
let obj = {
tom: {id: 0},
david: {id: 1},
john: {id: 2}
}
let ids = [1, 2];
let idsSet = new Set(ids);
const hasValidId = o => idsSet.has(o.id);
let res = R.filter(hasValidId, obj);
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
如果你阅读文档here很容易
您可以使用Object.entries
在纯JavaScript中执行此操作,并使用includes
进行解构,如下所示:
let obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
};
let ids = [1, 2];
let result = {};
Object.entries(obj).forEach(([name, { id }]) => {
if (ids.includes(id)) {
result[name] = { id: id };
}
});
console.log(result);
一般来说,您应该努力使用帮助您而不是对您不利的数据结构。
使用简化的数据结构如下所示:
const obj = [
{id: 0, name: 'tom'},
{id: 1, name: 'david'},
{id: 2, name: 'john'}
]
你可以使用innerJoin
:
innerJoin((cur, id) => cur.id === id, obj, [1, 2])
如何将原始数据结构转换为简化数据结构?
与Ramda一起分为两个步骤:
toPairs
将对象拆分为键/值对数组:
{tom:{id:0}} ~> [['tom', {id: 0}]]
[['tom', {id: 0}]] ~> [{name: 'tom', id: 0}]
const obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
}
const convert = R.compose(R.map(([name, id]) => ({name, ...id})), R.toPairs);
console.log(convert(obj))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
试试这个:
let obj = { tom: { id: 0 }, david: { id: 1}, john: {id: 2} }
let ids = [1, 2] ;
let result = {} ;
for ( var o in obj ) {
if (ids.includes(obj[o].id))
result[o] = obj[o];
}
console.log(result) ;
除非这是学习Ramda的练习,否则要注意想要在Ramda中这样做的想法。我是Ramda的主要作者之一,也是一个忠实粉丝,但我需要强调的是,它只是一个工具包而不是在某些情况下可以提供帮助。当它有所帮助时,很好,但它不应该是一个目标。
现在,我认为它可以在这里提供帮助。这就是我对Ramda的处理方式:
const matchIds = (obj, ids) => filter(propSatisfies(includes(__, ids), 'id'), obj)
let obj = {tom: {id: 0}, david: {id: 1}, john: {id: 2}}
let ids = [1, 2]
console.log(matchIds(obj, ids))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {__, filter, propSatisfies, includes} = R
</script>
另一种选择,特别是如果id列表不太可能比对象更改,则:
const matchIds = (ids) => filter(propSatisfies(includes(__, ids), 'id'))
let obj = {tom: {id: 0}, david: {id: 1}, john: {id: 2}}
let ids = [1, 2]
console.log(matchIds(ids)(obj))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {__, filter, propSatisfies, includes} = R
</script>
有一些理由不喜欢占位符('__
')。如果您有这种感觉,可以用includes(__, ids)
替换flip(includes)(ids)
。
我不接受我自己的建议。虽然我仍然会使用Ramda作为filter
,但这里不需要propSatisfies
。一个简单的lambda将是完美的:
const matchIds = (ids) => filter(({id}) => ids.includes(id))
这个更清洁,更易读,至少一旦你习惯了部分应用的Ramda规范。 (filter
有两个参数:谓词函数和用它过滤的对象。由于我们只提供第一个,这给了我们一个期望第二个的函数。当我们用对象调用那个结果函数时,就会发生过滤。)
我仍然使用Ramda的filter
的原因是它没有应用于对象的直接内置版本。 Ramda提供了一种简单的替代方法来编写一次性对象过滤。