簡體   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