2017-09-05 33 views
3

從對象的數組獲得一組重複的,含有JavaScript對象(JSON):
每個對象都有一個b屬性,和一個u屬性,ramda.js:使用鑑於這種陣列的特定屬性

(每個包含我不關心此練習的其他屬性)。

[ 
    { "b": "A", "u": "F", ... }, 
    { "b": "M", "u": "T", ... }, 
    { "b": "A", "u": "F", ... }, 
    { "b": "M", "u": "T", ... }, 
    { "b": "M", "u": "T", ... }, 
    { "b": "X", "u": "Y", ... }, 
    { "b": "X", "u": "G", ... }, 
] 

我想用ramda找出一組所有重複的。 結果應該看起來像這樣。

[ 
    { "b": "A", "u":"F" }, 
    { "b": "M", "u":"T" } 
] 

這兩個條目有重複,它們分別在原始列表中重複2次和3次。

編輯

我已經發現使用underscore一個解決方案,即保持原來的陣列元件,並完美地把他們分爲單打和重複。我更喜歡ramda.js,並且下劃線不僅僅給出了一組重複項 - 根據這個問題,所以我將問題留在開放中,直到有人可以用ramda回答。直到問題得到解答,我纔會用下劃線繼續前進。

我有一個repl是找到獨特的價值觀......作爲一個開始......

+0

你想要完整的重複項還是隻有那些匹配'b'和'u'的項? –

+0

不,只有匹配的字段,「b」和「u」 - 儘管爲了興趣 - 這將是很高興知道。我懷疑R.equals可能會滿足所有人的平等。 – Jim

+1

我花了很多時間試圖用R.head和R.tail來解決這個問題 - 得出這樣的結論:這是一個棘手的問題......嘗試以某種方式遍歷唯一列表,並從獨特的每場比賽的數據中刪除一個匹配似乎是正確的方法......但我還沒有設法讓組成正確呢。 – Jim

回答

2

這似乎過於複雜,不可能是性能良好,但是一個選項會是這樣:

const foo = pipe(
    project(['b', 'u']), 
    reduce(
    ({results, foundOnce}, item) => contains(item, results) 
     ? {results, foundOnce} 
     : contains(item, foundOnce) 
     ? {results: append(item, results), foundOnce} 
     : {results, foundOnce: append(item, foundOnce)}, 
    {results: [], foundOnce: []} 
), 
    prop('results') 
) 

foo(xs); //=> [{b: 'A', u: 'F'}, {b: 'M', u: 'T'}] 

也許這個版本是比較容易理解,但它通過使用一個額外的迭代數據:

const foo = pipe(
    project(['b', 'u']), 
    reduce(
    ({results, foundOnce}, item) => contains(item, foundOnce) 
     ? {results: append(item, results), foundOnce} 
     : {results, foundOnce: append(item, foundOnce)}, 
    {results: [], foundOnce: []} 
), 
    prop('results'), 
    uniq 
) 

repl here

+0

對不起,我現在不能檢查你的結果 - 我一直在慶祝 - 但我必須完全讚賞這種與此相關的扭曲心靈......我會在早上檢查它,並且贊成最好的我可以。你搖滾! - 僅供參考我對解決方案比對性能更感興趣 - 匹配列表非常短。 – Jim

-1

不與Ramda JS專家,但我認爲下面應該工作:

var p = [ 
    { "b": "A", "u": "F" }, 
    { "b": "A", "u": "F" }, 
    { "b": "A", "u": "F" }, 
    { "b": "A", "u": "F" }, 
    { "b": "A", "u": "F" }, 
    { "b": "M", "u": "T" } 
]; 
var dupl = n => n > 1; 
R.compose(
    R.map(JSON.parse), 
    R.keys, 
    R.filter(dupl), 
    R.countBy(String), 
    R.map(JSON.stringify) 
)(p) 

請讓我知道它是否。

+0

更新的答案調用正確的R方法('uniqBy') – 82Tuskers

+1

我相信問題是要求找到具有重複的元素集合。 –

+1

@StevenGoodman的確如此。讓我解決答案。感謝您指出。 – 82Tuskers

0

如果你不關心您的數據多次循環,你可以像這樣:

  • 創建一個只包含相關的道具部分副本,使用pick(你自己的想法)
  • 使用groupByhash函數來分組類似的對象。 (Alternativelysort第一和使用groupWith(equals)
  • 使用values
  • 過濾掉,只有1項陣列使用filter
  • 地圖上的結果獲取分組陣列(那些不欺騙...)並返回第一

    const containsMoreThanOne = compose(lt(1), length); 
    const hash = JSON.stringify; // Naive.. watch out for key-order! 
    
    const getDups = pipe(
        map(pick(["b", "u"])), 
        groupBy(hash), 
        values, 
        filter(containsMoreThanOne), 
        map(head) 
    ); 
    
    getDups(data); 
    

    工作:使用map(head)

在代碼中的每個陣列的元件在Ramda REPL演示。

更混合的方法是在一個reducer中抽取所有這些邏輯,但它對我來說看起來有點混亂......

const clean = pick(["b", "u"]); 
const hash = JSON.stringify; 
const dupReducer = hash => (acc, o) => { 
    const h = hash(o); 
    // Mutate internal state 
    acc.done[h] = (acc.done[h] || 0) + 1; 
    if (acc.done[h] === 2) acc.result.push(o); 

    return acc; 
    }; 


const getDups = (clean, hash, data) => 
    reduce(dupReducer(hash), { result: [], done: { } }, map(clean, data)).result; 

getDups(clean, hash, data); 

REPL