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

У меня есть два массива объектов, оба массива, содержащие ключ, пару значений. Моя цель состоит в том, чтобы назначить значение ключа из одного массива во второй массив, если строковое значение одного ключа name соответствует строковому значению другого ключа _id.

Я попытался объединить два массива в один массив и просто иметь один массив с объектами, но я все еще не уверен, как я могу назначить ключ и значение другим объектам на основе сопоставления значения ключа _id и name. Я знаю, как с тем же ключом, но как мы можем сделать это на основе другого ключа и того же значения? Это может быть плохой дизайн и практика, но так возвращаются данные. Это выполнимо? Я попытался использовать lodash, распространение операции, карту безуспешно.

arr1 = [
{"_id": "electronics", "number": 35 },
{"_id": "house Appliances", "number": 5 },
{"_id": "nothing", "number":0}
]

arr2 = [
{"name": "electronics", "purpose": "entertainment", "price": 100},
{"name": "house Appliances", "purpose": "general", "price": 200},
{"name": "watches", "purpose": "time", "price": 30} ]

combinedArrObj = [
{"name": "electronics", "number": 35, "purpose": "entertainment", "price": 100},
{"name": "house Appliances", "purpose": "general", "price": 200, "number": 5}, 
{"name": "watches", "purpose": "time", "price": 30}
 ]

Ответы [ 3 ]

1 голос
/ 11 июня 2019

Мне кажется, вам не нужно слишком усложнять это, если у вас будет только одна key value пара в array1.Просто преобразуйте в карту, а затем Array.map через array2 и Object.assign , чтобы создать объединение без лишних символов и т. Д.

const arr1 = [{"_id": "electronics", "number": 35 }, {"_id": "house Appliances", "number": 5 }]
const arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30}]

let map = arr1.reduce((acc, {_id, number}) => (acc[_id] = number, acc), {})

let result = arr2.map(({name, ...rest}) => 
  Object.assign({ name }, rest, map[name] ? { number: map[name] } : {}))

console.log(result)
0 голосов
/ 11 июня 2019

Создайте функцию с _.flow(), которая использует _.overArgs() для преобразования каждого массива в объект с соответствующим идентификатором (_id или name) в качестве ключа (с помощью _.keyBy()) и объединяют их в один объект. Преобразуйте объект обратно в массив, сопоставляя это, в то время как опуская поле _id:

const { flow, partialRight: pr, overArgs, merge, keyBy, map, omit } = _

const combineArrays = flow(
  overArgs((...objs) => merge({}, ...objs), [
    arr1 => keyBy(arr1, '_id'),
    arr2 => keyBy(arr2, 'name')    
  ]),
  pr(map, o => omit(o, '_id'))
)

const arr1 = [{"_id": "electronics", "number": 35 }, {"_id": "house Appliances", "number": 5 }]
const arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30}]
 
const combinedArrs = combineArrays(arr1, arr2)

console.log(combinedArrs)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

И более краткая версия, использующая lodash / fp :

const { flow, overArgs, merge, keyBy, map, omit } = _

const combineArrays = flow(
  overArgs(merge, [keyBy('_id'), keyBy('name')]),
  map(omit('_id'))
)

const arr1 = [{"_id": "electronics", "number": 35 }, {"_id": "house Appliances", "number": 5 }]
const arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30}]
 
const combinedArrs = combineArrays(arr1, arr2)

console.log(combinedArrs)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

В vanilla JS вы можете concat массивов, а затем использовать Array.reduce() для преобразования массивов в объект, используя _id или name в качестве ключа, и комбинирование предметов с одним и тем же ключом с объектным распространением . Затем преобразуйте обратно в массив с помощью Object.values():

const combineArrays = (arr1, arr2) => Object.values(
  arr1.concat(arr2) // combine the arrays
    .reduce((r, { _id, ...o }) => { // clone the object and remove _id if exists
      const key = _id || o.name // the key is the _id or the name if _id doesn't exist

      r[key] = r[key] ? { ...r[key], ...o } : o // if the key exists on the accumulator combine with current item, if not set current item to the key

      return r;
    }, {})
)

const arr1 = [{"_id": "electronics", "number": 35 }, {"_id": "house Appliances", "number": 5 }]
const arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30}]
 
const combinedArrs = combineArrays(arr1, arr2)

console.log(combinedArrs)
0 голосов
/ 11 июня 2019

Вы можете использовать уменьшить и найти

  • Сначала проверьте, присутствует ли совпадение _id в arr1 для соответствующего имени
  • если он присутствует, мы объединяем значение этого элемента в окончательный вывод
  • Иначе просто сохраните inp только в выводе

let arr1 = [{"_id": "electronics", "number": 35 },"_id": "house Appliances", "number": 5 }]

let arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30} ]

let final = arr2.reduce((op,inp)=>{
  let found = arr1.find(({_id})=>_id===inp.name)
  let name = inp.name
  op[name] = op[name] || {}
  if(found){
    let {_id, ...rest} = found
    op[name] = {...op[name], ...rest, ...inp}
  } else {
    op[name] = {...op[name], ...inp}
  }
  return op
},{})

console.log(final)
...