使用Ramda将两个数组与两个不同的键组合在一起

时间:2016-06-02 16:18:00

标签: javascript arrays ramda.js

我是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方法。

3 个答案:

答案 0 :(得分:5)

可以使用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)));
});

答案 1 :(得分:1)

您想要的可能是生成器。像这样:

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函数进行推广以获取任意生成器并将组合回调留给读者。

当然,解决这个问题的方法肯定比延迟序列更紧凑,但是它比非常简短且几乎肯定比重复搜索第二个数组的匹配更有效,并且它比维护和递增两个单独的索引变量以做两者都要少得多。一次通过。

由于您的评论总是匹配,您可以按上述方式排序,然后执行此操作:

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

答案 2 :(得分:1)

因为你想到了

  

“首先尝试一种简单的Javascript方法。”

这是使用Array.concatArray.findArray.indexOfArray.mapObject.keys和{{}的原生 JavaScript替代解决方案1}}功能:

Object.assign

输出:

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