LoDash - 如何通过公用键将一个 collections 值推送到另一个值
LoDash - How to push one collections values into another via common key
我有两个collections.
var a =
[
{unique_id: "001", state: "CO"},
{unique_id: "001", state: "TX"},
{unique_id: "001", state: "CC"},
{unique_id: "002", state: "CC"},
{unique_id: "002", state: "NY"}
]
和
var b =
[
{unique_id: "001", states:[]},
{unique_id: "002", states:[]}
]
我想得到:
var b =
[
{unique_id: "001", states:["CO","TX","CC"]},
{unique_id: "002", states:["CC","NY"]}
]
我应该提到,"b" 数组必须保持与它相同的顺序,并且一些 unique_id 没有值。
我一直在尝试使用 LoDash https://lodash.com/ - 所以如果有人能用 LoDash 解决这个问题那就太棒了!
此解决方案的时间复杂度不是最优的 ( O(n^2) ),但它可能会帮助您想出将值推入 "b":
的匹配方法
_.forEach(a, function(element1){
_.forEach(b, function(element2){
if (element2.unique_id === element1.unique_id) {
element2.states.push(element1.state);
}
});
});
也许更好的解决方案是使用 lodash 的 _.indexBy 方法通过对象的唯一 ID 为 b 中的对象编制索引。例如,您可以按如下方式为 b 中的对象编制索引:
var c = _.indexBy(b, 'unique_id')
这将导致:
{001:{unique_id: "001", states:[]}, 002: {unique_id: "002", states:[]}}
由于 c 数组中的对象指向内存中与 b 数组中相同的对象,我们可以直接改变 c 中的对象,b 将引用内存中那些更新的对象。所以:
_.forEach(a, function(element1){
if (element1.unique_id in c) {
c[element1.unique_id].states.push(element1.state);
}
})
现在,如果我们看一下 b 数组,我们会看到值为:
var b =
[
{unique_id: "001", states:["CO","TX","CC"]},
{unique_id: "002", states:["CC","NY"]}
]
这个解决方案的时间复杂度应该接近于 O(n),这比使用嵌套 _.forEach 方法要好得多。代码片段:
var a =
[
{unique_id: "001", state: "CO"},
{unique_id: "001", state: "TX"},
{unique_id: "001", state: "CC"},
{unique_id: "002", state: "CC"},
{unique_id: "002", state: "NY"}
];
var b =
[
{unique_id: "001", states:[]},
{unique_id: "002", states:[]}
];
var c = _.indexBy(b, 'unique_id');
_.forEach(a, function(element1){
if (element1.unique_id in c) {
c[element1.unique_id].states.push(element1.state);
}
});
document.writeln(JSON.stringify(b))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.js"></script>
_(a).groupBy('unique_id')
.map(function(item, key) {
return {
unique_id: key,
states: _.pluck(item, 'state')
};
})
.value()
您基本上是按 unique_id
对状态进行分组,然后将该对象映射到一个数组,其中每个项目都具有您需要的结构。
我有两个collections.
var a =
[
{unique_id: "001", state: "CO"},
{unique_id: "001", state: "TX"},
{unique_id: "001", state: "CC"},
{unique_id: "002", state: "CC"},
{unique_id: "002", state: "NY"}
]
和
var b =
[
{unique_id: "001", states:[]},
{unique_id: "002", states:[]}
]
我想得到:
var b =
[
{unique_id: "001", states:["CO","TX","CC"]},
{unique_id: "002", states:["CC","NY"]}
]
我应该提到,"b" 数组必须保持与它相同的顺序,并且一些 unique_id 没有值。
我一直在尝试使用 LoDash https://lodash.com/ - 所以如果有人能用 LoDash 解决这个问题那就太棒了!
此解决方案的时间复杂度不是最优的 ( O(n^2) ),但它可能会帮助您想出将值推入 "b":
的匹配方法_.forEach(a, function(element1){
_.forEach(b, function(element2){
if (element2.unique_id === element1.unique_id) {
element2.states.push(element1.state);
}
});
});
也许更好的解决方案是使用 lodash 的 _.indexBy 方法通过对象的唯一 ID 为 b 中的对象编制索引。例如,您可以按如下方式为 b 中的对象编制索引:
var c = _.indexBy(b, 'unique_id')
这将导致:
{001:{unique_id: "001", states:[]}, 002: {unique_id: "002", states:[]}}
由于 c 数组中的对象指向内存中与 b 数组中相同的对象,我们可以直接改变 c 中的对象,b 将引用内存中那些更新的对象。所以:
_.forEach(a, function(element1){
if (element1.unique_id in c) {
c[element1.unique_id].states.push(element1.state);
}
})
现在,如果我们看一下 b 数组,我们会看到值为:
var b =
[
{unique_id: "001", states:["CO","TX","CC"]},
{unique_id: "002", states:["CC","NY"]}
]
这个解决方案的时间复杂度应该接近于 O(n),这比使用嵌套 _.forEach 方法要好得多。代码片段:
var a =
[
{unique_id: "001", state: "CO"},
{unique_id: "001", state: "TX"},
{unique_id: "001", state: "CC"},
{unique_id: "002", state: "CC"},
{unique_id: "002", state: "NY"}
];
var b =
[
{unique_id: "001", states:[]},
{unique_id: "002", states:[]}
];
var c = _.indexBy(b, 'unique_id');
_.forEach(a, function(element1){
if (element1.unique_id in c) {
c[element1.unique_id].states.push(element1.state);
}
});
document.writeln(JSON.stringify(b))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.js"></script>
_(a).groupBy('unique_id')
.map(function(item, key) {
return {
unique_id: key,
states: _.pluck(item, 'state')
};
})
.value()
您基本上是按 unique_id
对状态进行分组,然后将该对象映射到一个数组,其中每个项目都具有您需要的结构。