Объединить массивы объектов на множественном ключе в Javascript - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть два массива объектов:

A = [
    { id1: "1", id2: "a", p1: "3", p2: "4" },
    { id1: "1", id2: "b", p1: "5", p2: "6" },
    { id1: "2", id2: "a", p1: "7", p2: "8" },
    { id1: "2", id2: "b", p1: "9", p2: "10" }
];


B = [
    { id1: "1", id2: "a", p3: "13", p4: "14" },
    { id1: "1", id2: "b", p3: "15", p4: "16" },
    { id1: "2", id2: "a", p3: "17", p4: "18" },
    { id1: "2", id2: "b", p3: "19", p4: "20" }
];

Мне нужна функция, которая создает внутреннее соединение между двумя объектами на основе двух свойств id1 и id2, объединяя другие свойства ( имена свойств никогда не равны, за исключением id1 и id2) Другими словами мне нужно в результате:

C = [
    { id1: "1", id2: "a", p1: "3", p2: "4", p3: "13", p4: "14" },
    { id1: "1", id2: "b", p1: "5", p2: "6", p3: "15", p4: "16" },
    { id1: "2", id2: "a", p1: "7", p2: "8", p3: "17", p4: "18" },
    { id1: "2", id2: "b", p1: "9", p2: "10", p3: "19", p4: "20" }
];

Здесь я могу найти способ сделать соединение, используя один единственный ключ. Мне нужно расширение для случая с несколькими ключами.

http://learnjsdata.com/combine_data.html

Ответы [ 3 ]

2 голосов
/ 24 апреля 2019

Если массивы очень большие, использование поиска типа @MarkMeyer показывает, что будет , возможно, будет лучшим вариантом. Но для небольших массивов, выполняющих простую карту, разброс массива и поиск работают нормально.

Как указал @ user11299053, это не эквивалент внутреннего присоединиться, может быть левое присоединение вместо этого .. Так что я оставлю это как есть, это может быть полезным. :)

const A=[
  {id1:"1", id2:"a", p1:"3", p2:"4"},
  {id1:"1", id2:"b", p1:"5", p2:"6"},
  {id1:"2", id2:"a", p1:"7", p2:"8"},
  {id1:"2", id2:"b", p1:"9", p2:"10"}
];

const B=[
  {id1:"1", id2:"a", p3:"13", p4:"14"},
  {id1:"1", id2:"b", p3:"15", p4:"16"},
  {id1:"2", id2:"a", p3:"17", p4:"18"},
  {id1:"2", id2:"b", p3:"19", p4:"20"}
];
  
const merged = B.map(item => ({
  ...A.find(
    f => f.id1 === item.id1 && f.id2 === item.id2),
  ...item
}));

console.log(merged);
2 голосов
/ 24 апреля 2019

Оба предоставленных ответа НЕ дают ожидаемый результат ( внутреннее объединение , которое должно содержать только соответствующих элементов из обоих наборов данных).

Я несколько расширил входные массивы, чтобы продемонстрировать разницу выходных данных для предоставленных ответов и моего:

const A = [
	{id1:"1", id2:"a", p1:"3", p2:"4"},
	{id1:"1", id2:"b", p1:"5", p2:"6"},
	{id1:"2", id2:"a", p1:"7", p2:"8"},
	{id1:"2", id2:"b", p1:"9", p2:"10"},
	{id1:"3", id2:"c", p1:"1", p2:"3"}
];

const B = [
	{id1:"1", id2:"a", p3:"13", p4:"14"},
	{id1:"1", id2:"b", p3:"15", p4:"16"},
	{id1:"2", id2:"a", p3:"17", p4:"18"},
	{id1:"2", id2:"b", p3:"19", p4:"20"},
	{id1:"4", id2:"k", p3:"11", p4:"13"}
];

const innerJoined = A.reduce((result, itemA) => {
  const itemB = B.find(itemB => itemB.id1 == itemA.id1 && itemB.id2 == itemA.id2);
  if(itemB) result.push({...itemA, ...itemB});
  return result;
}, []);

console.log(innerJoined);
2 голосов
/ 24 апреля 2019

Вы можете выполнить поиск на основе одного массива с помощью составного ключа из двух идентификаторов, затем выполнить цикл по второму, найти объединенный ключ и создать новый объект из двух элементов, используя Object.assign(). Это позволит вам составить список, не имея O (n²) решения поиска A для каждого элемента в B

let A=[
    {id1:"1", id2:"a", p1:"3", p2:"4"},
    {id1:"1", id2:"b", p1:"5", p2:"6"},
    {id1:"2", id2:"a", p1:"7", p2:"8"},
    {id1:"2", id2:"b", p1:"9", p2:"10"}
]

let B=[{id1:"1", id2:"a", p3:"13", p4:"14"},
       {id1:"1", id2:"b", p3:"15", p4:"16"},
       {id1:"2", id2:"a", p3:"17", p4:"18"},
       {id1:"2", id2:"b", p3:"19", p4:"20"}
]
  
let lookup = A.reduce((obj, item) => {
  obj[`${item.id1}_${item.id2}`] = item // key in form of id1_id2
  return obj
}, {})

let merged = B.reduce((arr, item) => {
  if (lookup[`${item.id1}_${item.id2}`]) {
    arr.push(Object.assign({}, lookup[`${item.id1}_${item.id2}`], item))
  }
  return arr
}, [])

console.log(merged)

Вам просто нужно убедиться, что разделитель ключа (_ здесь) не существует в ваших идентификаторах. Если это проблема, вы можете создать вложенный объект с поиском типа obj[id1][id2]:

let lookup = A.reduce((obj, item) => {
    if (!obj[item.id1]) obj[item.id1] = {}
    obj[item.id1][item.id2] = item
    return obj
}, {} )

и отрегулируйте обратный вызов reduce() для соответствия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...