簡體   English   中英

使用Ramda將兩個具有兩個不同鍵的數組組合在一起

[英]Combine two arrays with two different keys with Ramda

我是Ramda和currying的新手,但想結合兩個不同的數組。 鑒於:

var array1 = [
 {_id: 0, x: 10},
 {_id: 1, x: 30}
];

var array2 = [
  {UUID: 0, y: 20},
  {UUID: 1, y: 60}
];

我想在_id === UUID地方加入他們,得到這樣的東西:

var result = [
  {_id: 0, UUID: 0, x: 10, y: 20},
  {_id: 1, UUID: 1, x: 30, y: 60}
];

我看了看文檔, whereintersectionmerge似乎是要使用的文檔。 但是intersectionmerge期望使用相同的鍵。 似乎在where ,但是我仍然不確定如何告訴我我想要兩個不同的鍵具有相同的值。

因此,我認為可以使用forEachfindequals一個或多個來鏡像POJS方式。 下面是我在想什么(無intersectionwhere使用至今):

import r from 'ramda';
var result = 
  r.forEach(
    r.find(
      r.equals(
        r.prop('UUID', r._),
        r.prop('_id', r._)
      ), data, metadata);

我只停留在如何從兩個數組中檢查單獨的鍵( UUID_id ),同時又保留功能符號的情況下。 我相信我會做錯所有的事情,但是我的想法很沮喪,我將首先嘗試簡單的Javascript方法。

可以使用R.indexByR.mergeWithR.merge

//  propMerge :: String -> String -> Array Object -> Array Object -> Array Object
var propMerge = R.curry(function(k1, k2, xs1, xs2) {
  return R.values(R.mergeWith(R.merge,
                              R.indexBy(R.prop(k1), xs1),
                              R.indexBy(R.prop(k2), xs2)));
});

您想要的可能是使用生成器 像這樣:

arr1.sort((a, b) => a._id - b._id);
arr2.sort((a, b) => a.UUID - b.UUID);

let step1 = arr1[Symbol.iterator]();
let step2 = arr2[Symbol.iterator]();

let zipSeq = (first, second) => {
  let done = false, result = [];
  while (!done) {
    let obj = first.next();
    let check = second.next();
    while (check.value.UUID !== obj.value._id && !check.done) {
      check = second.next(); // make sure we account for non-sequential
    }
    result.push(Object.assign({}, obj.value, check.value));
    done = obj.done || check.done;
  }
  return result;
};

let mixed = zipSeq(step1, step2);

通用化zipSeq函數以采用任意生成器,並且將合並回調作為zipSeq留給讀者。

解決此問題的方法肯定比惰性序列更緊湊,但是比重復搜索第二個數組的匹配項要短得多,而且幾乎可以肯定是性能更高的,而且比維護和遞增兩個單獨的索引變量來一次完成這兩個過程要簡單得多。

由於根據您的評論始終存在匹配項,因此您可以按上述進行排序,然后執行以下操作:

let results = R.zip(arr1, arr2, (a, b) => Object.assign({}, a, b));

既然你想到了

“首先嘗試使用簡單的Javascript方法。”

這是使用Array.concatArray.findArray.indexOfArray.mapObject.keysObject.assign函數的原生 JavaScript替代解決方案:

var keys = ['_id', 'UUID'], result = {};

array1.concat(array2).forEach(function(obj){
    var value = obj[Object.keys(obj).find((v) => keys.indexOf(v) !== -1 )],
        props = Object.keys(obj);  // array of property names of the current object

    result[value] = result[value] || obj;
    if (Object.keys(result[value]).indexOf(props[0]) === -1) {
        Object.assign(result[value], obj);  // "merging" two objects
    }
}, result);
result = Object.keys(result).map((k) => result[k]);

console.log(JSON.stringify(result, 0, 4));

輸出:

[
    {
        "_id": 0,
        "x": 10,
        "UUID": 0,
        "y": 20
    },
    {
        "_id": 1,
        "x": 30,
        "UUID": 1,
        "y": 60
    }
]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM