简体   繁体   English

JavaScript:两个数组的类似 SQL 的连接

[英]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:注意:

  1. This is "joining" by the id "column."这是通过id “列”“加入”。
  2. The order of the result is the order of the one array (sorting by ID is only coincidentally the same order)结果的顺序就是one数组的顺序(按ID排序只是巧合顺序一样)
  3. Fields from both arrays exist on the result结果中存在来自两个数组的字段

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 mergemapfind函数。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM