[英]Combine two arrays with two different keys with Ramda
I'm new to Ramda and currying but would like to combine two different arrays. 我是Ramda和currying的新手,但想结合两个不同的数组。 Given:
鉴于:
var array1 = [
{_id: 0, x: 10},
{_id: 1, x: 30}
];
var array2 = [
{UUID: 0, y: 20},
{UUID: 1, y: 60}
];
I would like to join them where _id === UUID
to get something like this: 我想在
_id === UUID
地方加入他们,得到这样的东西:
var result = [
{_id: 0, UUID: 0, x: 10, y: 20},
{_id: 1, UUID: 1, x: 30, y: 60}
];
I looked at the docs and where
, intersection
, and merge
seemed to be the ones to use. 我看了看文档,
where
, intersection
和merge
似乎是要使用的文档。 But intersection
and merge
expect the same key. 但是
intersection
和merge
期望使用相同的键。 where
seems to be the ticket, but I'm still not sure how to tell it that I want two different keys to have the same value. 似乎在
where
,但是我仍然不确定如何告诉我我想要两个不同的键具有相同的值。
So I figure I can do it mirroring the POJS way, using one or more of forEach
, find
, and equals
. 因此,我认为可以使用
forEach
, find
和equals
一个或多个来镜像POJS方式。 Here's what I was thinking (no intersection
or where
usage so far): 下面是我在想什么(无
intersection
或where
使用至今):
import r from 'ramda';
var result =
r.forEach(
r.find(
r.equals(
r.prop('UUID', r._),
r.prop('_id', r._)
), data, metadata);
I'm stuck at just how to check for the separate keys ( UUID
and _id
) from the two arrays while keeping the functional notation. 我只停留在如何从两个数组中检查单独的键(
UUID
和_id
),同时又保留功能符号的情况下。 I believe I'm going about it all wrong but my mind is rutted and I'll try a plain Javascript approach first. 我相信我会做错所有的事情,但是我的想法很沮丧,我将首先尝试简单的Javascript方法。
One could use R.indexBy
, R.mergeWith
, and R.merge
: 可以使用
R.indexBy
, R.mergeWith
和R.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)));
});
What you want is likely to use generators . 您想要的可能是使用生成器 。 Like so:
像这样:
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);
Generalizing the zipSeq
function to take arbitrary generators and a combining callback is left as an exercize to the reader. 通用化
zipSeq
函数以采用任意生成器,并且将合并回调作为zipSeq
留给读者。
There are certainly more compact ways to solve this than lazy sequences, but its pretty short and almost certainly more performant than repeatedly searching the second array for matches, and its far less imperative than maintaining and incrementing two separate indexing variables to do both in one pass. 解决此问题的方法肯定比惰性序列更紧凑,但是比重复搜索第二个数组的匹配项要短得多,而且几乎可以肯定是性能更高的,而且比维护和递增两个单独的索引变量来一次完成这两个过程要简单得多。
Since per your comment there are always matches, you can sort as above and then do this: 由于根据您的评论始终存在匹配项,因此您可以按上述进行排序,然后执行以下操作:
let results = R.zip(arr1, arr2, (a, b) => Object.assign({}, a, b));
Since you had in mind to 既然你想到了
" try a plain Javascript approach first."
“首先尝试使用简单的Javascript方法。”
here is a native JavaScript alternative solution using Array.concat
, Array.find
, Array.indexOf
, Array.map
, Object.keys
and Object.assign
functions: 这是使用
Array.concat
, Array.find
, Array.indexOf
, Array.map
, Object.keys
和Object.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));
The output: 输出:
[
{
"_id": 0,
"x": 10,
"UUID": 0,
"y": 20
},
{
"_id": 1,
"x": 30,
"UUID": 1,
"y": 60
}
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.