[英]JavaScript: SQL-like join of two arrays
I have arrays like this:我有这样的数组:
const one = [
{id: 1, field1: "a"},
{id: 2, field1: "b"},
{id: 3, field1: "c"},
{id: 4, field1: "d"}
]
const two = [
{id: 4, field2: "4"},
{id: 1, field2: "1"}
]
// what I want to achieve:
const result = [
{id: 1, field1: "a", field2: "1"},
{id: 4, field1: "d", field2: "4"}
]
I want to merge one and two, so I get the result.我想合并一和二,所以我得到了结果。 This is very similar to a SQL join, but I want to do all of this in JavaScript code.
这与 SQL 连接非常相似,但我想在 JavaScript 代码中完成所有这些。 Notice:
注意:
id
"column."id
“列”“加入”。one
array (sorting by ID is only coincidentally the same order)one
数组的顺序(按ID排序只是巧合顺序一样)I've figured out how to do this on my own, but the code is clunky and difficult to read.我已经想出了如何自己做到这一点,但代码笨拙且难以阅读。 Basically, you filter over
one
and remove elements that don't exist in two
, then you map over one
and merge the fields of the two
array.基本上,您过滤
one
并删除two
不存在的元素,然后您映射one
并合并two
数组的字段。
Is there a more concise way of achieving this?有没有更简洁的方法来实现这一目标? I'm using lodash, and I was hoping there was a function in there to make this easier, but I haven't found any.
我正在使用 lodash,我希望有一个功能可以让这更容易,但我还没有找到任何功能。
Create a dictionary or Map of the 2nd array by the key ( id
), and then filter the 1st array, and keep only items that appear in the dictionary.通过键(
id
)创建第二个数组的字典或映射,然后过滤第一个数组,只保留字典中出现的项目。 Afterwards, map the remaining items, and add the relevant items from the dictionary.之后,映射剩余的项目,并添加字典中的相关项目。
const joinBy = (arr1, arr2, key) => { const arr2Dict = _.keyBy(arr2, key) return arr1 .filter(item => item[key] in arr2Dict) .map(item => ({ ...item, ...arr2Dict[item[key]] })) } const one = [{id: 1, field1: "a"},{id: 2, field1: "b"},{id: 3, field1: "c"},{id: 4, field1: "d"}] const two = [{id: 4, field2: "4"},{id: 1, field2: "1"}]; const result = joinBy(one, two, 'id') console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
If you don't want to use lodash, you can easily replace _.keyBy()
, and create an object using Array.reduce()
or create a Map with Array.map()
.如果您不想使用 lodash,您可以轻松替换
_.keyBy()
,并使用Array.reduce()
创建一个对象或使用Array.map()
创建一个 Map 。
const joinBy = (arr1, arr2, key) => { const arr2Dict = new Map(arr2.map(o => [o[key], o])) return arr1 .filter(item => arr2Dict.has(item[key])) .map(item => ({ ...item, ...arr2Dict.get(item[key]) })) } const one = [{id: 1, field1: "a"},{id: 2, field1: "b"},{id: 3, field1: "c"},{id: 4, field1: "d"}] const two = [{id: 4, field2: "4"},{id: 1, field2: "1"}]; const result = joinBy(one, two, 'id') console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
You can use merge
, map
and find
functions from lodash
.您可以使用
lodash
merge
、 map
和find
函数。 For sorting - sortBy
.用于排序 -
sortBy
。
_.sortBy(
_.map(two, (n) => _.merge(n, _.find(one, ['id', n.id]))),
(o) => _.findIndex(one, ['id', o.id]),
);
const one = [{id: 1, field1: "a"},{id: 2, field1: "b"},{id: 3, field1: "c"},{id: 4, field1: "d"}], two = [{id: 4, field2: "4"},{id: 1, field2: "1"}]; const r = _.sortBy( _.map(two, (n) => _.merge(n, _.find(one, ['id', n.id]))), (o) => _.findIndex(one, ['id', o.id]), ); console.log(r);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>
If you have different fields, you could take an object with the reference to the items and map two
and sort by id
.如果您有不同的字段,您可以获取一个引用项目的对象并映射
two
并按id
排序。
const one = [{ id: 1, field1: "a" }, { id: 2, field1: "b" }, { id: 3, field1: "c" }, { id: 4, field1: "d" }], two = [{ id: 4, field2: "4" }, { id: 1, field2: "1" }], fromOne = Object.fromEntries(one.map((object, index) => [object.id, { object, index }])), result = two .map(o => ({ ...fromOne[o.field2].object, ...o })) .sort((a, b) => fromOne[a.field2].index - fromOne[b.field2].index); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.