[英]Filter object base on an array with Ramda.js
let obj = {
tom: {
id: 0
},
david: {
id: 1
},
john: {
id: 2
}
}
let ids = [1, 2]
I want to filter the obj based on ids. 我想基于id过滤obj。
The result I want is 我想要的结果是
{ david: { id: 1 }, john: { id: 2 } } {david:{id:1},john:{id:2}}
Because ids above is [1, 2]. 因为上面的id是[1,2]。
I want to do this with Ramda.js. 我想用Ramda.js做到这一点。
Plase help me. 请帮助我。
Ok, I'm sorry. 好吧,我很抱歉。
I did something like this. 我做了这样的事情。
let obj2 = {}
ids.forEach((x) => {
obj2 += R.filter(y => y.id === x, obj)
})
obj = obj2
But, it is not correct. 但是,这是不正确的。
And I don't want to use forEach. 而且我不想使用forEach。
I want to do with Ramda.js . 我想做Ramda.js。
You can do this only using Javascript
, first you can create a set with the ids
you want to keep (check if set has an element is O(1)
). 您只能使用Javascript
来执行此操作,首先可以使用要保留的ids
创建一个set(检查set是否具有元素为O(1)
)。 Then, you can loop on the original object
and add the key
with his value
on a new object
if the set has the related id
: 然后,您可以在原始object
上循环播放,并在key
集具有相关id
将key
及其value
添加到新object
:
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;}
With Ramda you can do like this: 使用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>
You can do it in pure JavaScript by using Object.entries
and destructuring with includes
like so: 您可以通过使用Object.entries
并使用includes
来在纯JavaScript中进行操作:
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);
Generally speaking, you should strive to work with data structures that help you rather than work against you. 一般来说,您应该努力使用对您有所帮助的数据结构,而不是不利于您的工作。
With a simplified data structure such as this one below: 具有简化的数据结构,如下所示:
const obj = [
{id: 0, name: 'tom'},
{id: 1, name: 'david'},
{id: 2, name: 'john'}
]
You could use innerJoin
: 您可以使用innerJoin
:
innerJoin((cur, id) => cur.id === id, obj, [1, 2])
How to convert your original data structure into a simplified one? 如何将原始数据结构转换为简化的数据结构?
It can be a two-step process with Ramda: Ramda可以分为两个步骤:
Split your object into an array of key/value pairs with toPairs
: 使用toPairs
将您的对象拆分为键/值对的toPairs
:
{tom:{id:0}} ~> [['tom', {id: 0}]]
Map each pair into an object: 将每对映射到一个对象:
[['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>
Try This: 尝试这个:
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) ;
Unless this is an exercise in learning Ramda, beware of the idea of wanting to do this in Ramda. 除非这是学习Ramda的练习,否则请注意要在Ramda中进行此操作的想法。 I'm one of the primary authors of Ramda, and a big fan, but I need to stress that it's simply a toolkit than can help in some situations. 我是Ramda的主要作者之一,也是忠实的拥护者,但我需要强调的是,它只是一个工具包,在某些情况下无济于事。 When it helps, great, but it shouldn't be a goal. 如果有帮助,那很好,但这不是目标。
Now, I do think it can help here. 现在,我认为这可以为您提供帮助。 This is what I would do with 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>
An alternative, especially if the list of ids is less likely to change than the object, is this: 一种替代方法是,尤其是如果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>
There are some reasons not to like the placeholder (' __
'). 有一些原因不喜欢占位符(' __
')。 If you feel that way, you can replace includes(__, ids)
with flip(includes)(ids)
. 如果您有这种感觉,可以用flip(includes)(ids)
替换includes(__, ids)
flip(includes)(ids)
。
I don't take my own advice here. 我在这里不接受我的建议。 While I still would use Ramda for the filter
, there is no need for propSatisfies
here. 尽管我仍将propSatisfies
用作filter
,但这里不需要propSatisfies
。 A simple lambda would be perfectly fine: 一个简单的lambda就可以了:
const matchIds = (ids) => filter(({id}) => ids.includes(id))
This is much cleaner and more readable, at least once you're used to the Ramda norm of partial application. 至少一旦您习惯了部分应用程序的Ramda规范,它就会更干净,更易读。 ( filter
takes two arguments: the predicate function and the object to filter with it. Since we only supply the first, this gives us back a function expecting the second. When we call that resulting function with the object, the filtering happens.) ( filter
有两个参数:谓词函数和要使用它进行过滤的对象。由于我们只提供第一个参数,所以这给了我们一个期望第二个函数的函数。当我们用对象调用该结果函数时,就会进行过滤。)
The reason I would still use Ramda's filter
is that there is no direct built-in version of it as applied to objects. 我仍将使用Ramda的filter
的原因是,它没有直接内置于对象的内置版本。 Ramda supplies a simple alternative to writing a one-off object filtering. Ramda提供了一种简单的方法来编写一次性对象过滤。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.