简体   繁体   English

使用Ramda.js在数组上过滤对象

[英]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集具有相关idkey及其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;} 


Update to use Ramda: 更新为使用Ramda:

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> 

Easy if you read the documentation here 如果您在此处阅读文档,那很容易

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可以分为两个步骤:

  1. Split your object into an array of key/value pairs with toPairs : 使用toPairs将您的对象拆分为键/值对的toPairs

     {tom:{id:0}} ~> [['tom', {id: 0}]] 
  2. 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)

Update 更新

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM