使用Ramda.js过滤基于数组的对象

时间:2019-03-08 03:55:46

标签: javascript arrays object ramda.js

let obj = {
  tom: {
    id: 0
  },
  david: {
    id: 1
  },
  john: {
    id: 2
  }
}

let ids = [1, 2]

我想根据ID过滤obj。

我想要的结果是

{       大卫: {         编号:1       },       约翰: {         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。

5 个答案:

答案 0 :(得分:2)

您只能使用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;}
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);


更新为使用Ramda:

使用Ramda,您可以这样做:

.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>
> library(rJava)
Error: package or namespace load failed for ‘rJava’:
 .onLoad failed in loadNamespace() for 'rJava', details:
  call: dyn.load(file, DLLpath = DLLpath, ...)
  error: unable to load shared object '/Library/Frameworks/R.framework/Versions/3.5/Resources/library/rJava/libs/rJava.so':
  dlopen(/Library/Frameworks/R.framework/Versions/3.5/Resources/library/rJava/libs/rJava.so, 6): Library not loaded: /Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/lib/server/libjvm.dylib
  Referenced from: /Library/Frameworks/R.framework/Versions/3.5/Resources/library/rJava/libs/rJava.so
  Reason: image not found

轻松阅读文档here

答案 1 :(得分:1)

您可以在纯JavaScript中使用Object.entries并使用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);

答案 2 :(得分:1)

通常来说,您应该努力使用对您有所帮助的数据结构,而不是对您不利。

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

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将对象拆分为键/值对数组:

    {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>

答案 3 :(得分:0)

尝试一下:

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) ;

答案 4 :(得分:0)

除非这是学习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提供了一种简单的方法来编写一次性对象过滤。