繁体   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]

我想基于id过滤obj。

我想要的结果是

{david:{id:1},john:{id:2}}

因为上面的id是[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(检查set是否具有元素为O(1) )。 然后,您可以在原始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;} 


更新为使用Ramda:

使用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> 

如果您在此处阅读文档,那很容易

您可以通过使用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); 

一般来说,您应该努力使用对您有所帮助的数据结构,而不是不利于您的工作。

具有简化的数据结构,如下所示:

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

  1. 使用toPairs将您的对象拆分为键/值对的toPairs

     {tom:{id:0}} ~> [['tom', {id: 0}]] 
  2. 将每对映射到一个对象:

     [['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> 

有一些原因不喜欢占位符(' __ ')。 如果您有这种感觉,可以用flip(includes)(ids)替换includes(__, ids) flip(includes)(ids)

更新

我在这里不接受我的建议。 尽管我仍将propSatisfies用作filter ,但这里不需要propSatisfies 一个简单的lambda就可以了:

const matchIds = (ids) => filter(({id}) => ids.includes(id))

至少一旦您习惯了部分应用程序的Ramda规范,它就会更干净,更易读。 filter有两个参数:谓词函数和要使用它进行过滤的对象。由于我们只提供第一个参数,所以这给了我们一个期望第二个函数的函数。当我们用对象调用该结果函数时,就会进行过滤。)

我仍将使用Ramda的filter的原因是,它没有直接内置于对象的内置版本。 Ramda提供了一种简单的方法来编写一次性对象过滤。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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