Как я могу объединить два массива объектов с двумя разными размерами, используя пару ключ-значение, чтобы объединить их в один массив? - PullRequest
0 голосов
/ 06 марта 2019

У меня есть два массива объектов, которые выглядят в формате JSON:

   {
  "Arr1":
   [
    { "_id": "firstSub1", "count": 1, "price": 4 },
    { "_id": "firstSub2", "count": 2, "price": 7 },
    { "_id": "firstSub3", "count": 3, "price": 1 }
    { "_id": "firstSub4", "count": 4, "price": 1 }
   ],

    "Arr2":
     [
      { "name": "firstSub1", "date": 05 / 20 / 1998, "type": sometype1 },
      { "name": "firstSub2"  "date": 12 / 22 / 2011, "type": sometype2 },
      { "name": "firstSub3", "date": 09 / 23 / 2004, "type": sometype3 }
      { "name": "firstSub9", "date": 09 / 23 / 2004, "type": sometype9 }
    ]
//Desired Output
    "finalArray":
     [
      { "name": "firstSub1", "date": 05 / 20 / 1998, "type": sometype1, "count": 1, "price": 4 },  
      { "name": "firstSub2"  "date": 12 / 22 / 2011, "type": sometype2, "count": 2, "price": 7 },
      { "name": "firstSub3", "date": 09 / 23 / 2004, "type": sometype3, "count": 3, "price": 1 },
      { "name": "firstSub9", "date": 09 / 23 / 2004, "type": sometype9 },
      { "_id": "firstSub4", "count": 4, "price": 1 }
          ]   

}

Мне нужно сравнить _id в первом массиве и посмотреть, есть ли совпадение с name в Arr2, и сопоставить их, если _id === name.

Я пытался использовать lodash и его undescores, и отображать такие функции:

  mergeArray() {
    .... //pulling data

    let Arr1 = data['Arr1Data'];
    let Arr2 = data['Arr2Data'];

    let finalArray = Arr2.map((e, _) =>
      (_ = Arr1.find((q) => e.name === q._id)) ?
        { ...e, ..._ } : e)
    console.log(finalArray)
  }

Все данные из Arr2 возвращаются и объединяются только с половиной данных Arr1, мои данные не возвращаются с желаемым выводом ... как я могу отобразить эти два массива и иметь объединение и пересечение?

Ответы [ 4 ]

1 голос
/ 06 марта 2019

Используя vanilla Js, вы можете получить массив уникальных _id и name из обоих массивов, выполнить цикл через него и соединить объект из обоих массивов, который соответствует текущему id в итерации:

дедуплицированный массив id с и name с:

const ids = [...new Set([...Arr1.map(e => e._id), ...Arr2.map(e => e.name)])];

Цикл для объединения элементов из обоих массивов:

const result = ids.map(e => ({
  ...Arr1.find(o => o._id === e),
  ...Arr2.find(o => o.name === e)
}))

const Arr1 = [{"_id": "firstSub1","count": 1,"price": 4},{"_id": "firstSub2","count": 2,"price": 7},{"_id": "firstSub3","count": 3,  "price": 1}, {"_id": "firstSub4","count": 4,"price": 1}];

const Arr2 = [{"name": "firstSub1","date": "05 / 20 / 1998","type": "sometype1"}, {"name": "firstSub2","date": "12 / 22 / 2011","type": "sometype2"}, {"name": "firstSub3","date": "09 / 23 / 2004","type": "sometype3"}, {"name": "firstSub9","date": "09 / 23 / 2004","type": "sometype9"}];

const ids = [...new Set([...Arr1.map(e => e._id), ...Arr2.map(e => e.name)])];

const result = ids.map(e => ({
  ...Arr2.find(o => o.name === e),
  ...Arr1.find(o => o._id === e)
}))
console.log(result)

РЕДАКТИРОВАТЬ: Вы можете настроить возвращенный объект в .map() для удаления свойств (например, _id):

const Arr1 = [{"_id": "firstSub1","count": 1,"price": 4},{"_id": "firstSub2","count": 2,"price": 7},{"_id": "firstSub3","count": 3,  "price": 1}, {"_id": "firstSub4","count": 4,"price": 1}];

const Arr2 = [{"name": "firstSub1","date": "05 / 20 / 1998","type": "sometype1"}, {"name": "firstSub2","date": "12 / 22 / 2011","type": "sometype2"}, {"name": "firstSub3","date": "09 / 23 / 2004","type": "sometype3"}, {"name": "firstSub9","date": "09 / 23 / 2004","type": "sometype9"}];

const ids = [...new Set([...Arr1.map(e => e._id), ...Arr2.map(e => e.name)])];

const result = ids.map(e => {
  const obj = {
    ...Arr2.find(o => o.name === e),
    ...Arr1.find(o => o._id === e)
  }
  
  if(obj.name && obj._id) delete obj._id;
  
  return obj;
})
console.log(result)
0 голосов
/ 06 марта 2019

Вы можете использовать lodash _.flow(), чтобы создать функцию, которая объединяет массивы, группирует их по name или _id (все, что найдено на объекте). Если группа содержит более 1 элемента, она объединяется в один объект, а свойство _id опускается.

const { flow, partialRight: pr, concat, groupBy, map, merge, has, head, omit } = _

const fn = flow(
  concat, // combine to a single array
  pr(groupBy, o => o.name || o._id), // group by the value of name or _id
  pr(map, o => o.length === 1 ? head(o) : _.omit( // if a group contains 2 items merge them, and remove _id
    merge({}, ...o),
    '_id'
  )),
)

const Arr1 = [{"_id": "firstSub1","count": 1,"price": 4},{"_id": "firstSub2","count": 2,"price": 7},{"_id": "firstSub3","count": 3,  "price": 1}, {"_id": "firstSub4","count": 4,"price": 1}]

const Arr2 = [{"name": "firstSub1","date": "05 / 20 / 1998","type": "sometype1"}, {"name": "firstSub2","date": "12 / 22 / 2011","type": "sometype2"}, {"name": "firstSub3","date": "09 / 23 / 2004","type": "sometype3"}, {"name": "firstSub9","date": "09 / 23 / 2004","type": "sometype9"}]

const result = fn(Arr2, Arr1)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
0 голосов
/ 06 марта 2019

Можно выполнить сортировку по name и сравнить имя индекса i + 1, чтобы проверить, следует ли объединить индекс i + 1 и индекс i или если у объекта нет пары для объединения.

Например, сортировка по name означает, что следующим объектом / индексом будет пара.

[{name: "firstSub1", count: 1}, {name: "firstSub1", date: "dd / mm / yyyy"}] // Pair found

или

[{name: "firstSub1", count: 1}, {name: "firstSub2", count: 1}] // There is no a pair

Этопредполагает, что есть максимум одна пара

let obj = {  "Arr1": [{      "_id": "firstSub1",      "count": 1,      "price": 4    },    {      "_id": "firstSub2",      "count": 2,      "price": 7    },    {      "_id": "firstSub3",      "count": 3,      "price": 1    },    {      "_id": "firstSub4",      "count": 4,      "price": 1    }  ],  "Arr2": [{      "name": "firstSub1",      "date": "05 / 20 / 1998",      "type": "sometype1"    },    {      "name": "firstSub2",      "date": "12 / 22 / 2011",      "type": "sometype2"    },    {      "name": "firstSub3",      "date": "09 / 23 / 2004",      "type": "sometype3"    },    {      "name": "firstSub9",      "date": "09 / 23 / 2004",      "type": "sometype9"    }  ]};

// All objects in one array.
let merge = [...obj.Arr2, 
             // The map is to change _id by name, this is used later.
             ...obj.Arr1.map(({_id, count, price}) => ({name: _id, count, price}))]
                  .sort((a, b) => a.name.localeCompare(b.name));

// This approach doesn't mutate the source objects.
let result = [];
for (let i = 0; i < merge.length;) {
  if (merge[i + 1] && merge[i + 1].name === merge[i].name) {
    result.push(Object.assign(Object.create(null), merge[i], merge[i + 1]));
    i++;
  } else result.push(merge[i]);
  i++;
}

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 06 марта 2019

Одним из решений является использование Array.reduce () , начиная с accumulator, равного копии Arr2 (JSON.parse(JSON.stringify(Arr2))), поэтому мы не изменяем исходный массив Arr2,Теперь, итерируя по Arr1, если мы нашли совпадение, мы добавляем связанные свойства, используя Object.assign () к связанному объекту на accumulator, в противном случае мы помещаем весь объект вaccumulator:

const Arr1 = [
    {"_id": "firstSub1", "count": 1, "price": 4},
    {"_id": "firstSub2", "count": 2, "price": 7},
    {"_id": "firstSub3", "count": 3, "price": 1},
    {"_id": "firstSub4", "count": 4, "price": 1}
];

const Arr2 = [
    {"name": "firstSub1", "date": "05/20/1998", "type": "sometype1"},
    {"name": "firstSub2",  "date": "12/22/2011", "type": "sometype2"},
    {"name": "firstSub3", "date": "09/23/2004", "type": "sometype3"},
    {"name": "firstSub9", "date": "09/23/2004", "type": "sometype9"}
];

let res = Arr1.reduce((acc, {_id, count, price}) =>
{
    let fIdx = acc.findIndex(({name}) => name === _id);

    if (fIdx >= 0)
        Object.assign(acc[fIdx], {count, price});
    else
        acc.push({_id, count, price});
        
    return acc;
}, JSON.parse(JSON.stringify(Arr2)));

console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
...