Объединить /добавить объект в массив — Javscript

#javascript #arrays #lodash

#javascript #массивы #Lodash

Вопрос:

У меня есть два массива объектов. Моя цель — заменить объект из второго массива на первый на основе «id». У меня есть рабочее решение, но я хотел бы расширить его, добавив объект в первый массив, если значение не найдено. Пожалуйста, посоветуйте.

 function mergeById(arr) {
  return {
    with: function(arr2) {
      return _.map(arr, item => {
        return _.find(arr2, obj => obj.id === item.id) || item
      })
    }
  }
}

var result = mergeById([{
      id: '124',
      name: 'qqq'
    },
    {
      id: '589',
      name: 'www'
    },
    {
      id: '567',
      name: 'rrr'
    }
  ])
  .with([{
    id: '124',
    name: 'ttt'
  }, {
    id: '45',
    name: 'yyy'
  }])

console.log(result);

/**
[
  {
    "id": "124",
    "name": "ttt"
  },
  {
    "id": "589",
    "name": "www"
  },
  {
    "id": "567",
    "name": "rrr"
  },
  {
    id: '45',
    name: 'yyy'
  }
]
**/ 
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script> 

Пожалуйста, посоветуйте.

Ответ №1:

Вам нужно отфильтровать второй массив и добавить значения, у которых нет общего идентификатора.

 function mergeById(arr) {
    return {
        with: function(arr2) {
            return [
                ..._.map(arr, item => _.find(arr2, obj => obj.id === item.id) || item),
                ..._.filter(arr2, item => !_.some(arr, obj => obj.id === item.id))
            ];
        }
    }
}

var result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
      .with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }]);

console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script> 

Более короткий подход с Map одиночными циклами и для каждого массива.

 function mergeById(array) {
    const
        add2map = (m, o) => m.set(o.id, o),
        map = array.reduce(add2map, new Map);
    return {
        with: function(array2) {
            return Array.from(array2
                .reduce(add2map, map)
                .values()
            );
        }
    }
}

var result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
      .with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }]);

console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Комментарии:

1. Спасибо, как всегда 🙂

Ответ №2:

Используется _.differenceBy(arr2, arr, 'id') для поиска всех элементов, которые появляются в arr2 , которые не имеют аналога в arr by id , и связывают их с результатами _.map() действия.

Примечание: вместо того, чтобы использовать _.find() (O(n)) на каждой итерации, выполните итерацию arr2 один раз с _.keyBy() помощью (O(n)) для создания словаря { [id]: item } , а затем получите элементы в O(1) .

 const mergeById = arr => ({
  with(arr2) {
    const arr2Dict = _.keyBy(arr2, 'id')

    return _.map(arr, item => arr2Dict[item.id] || item)
      .concat(_.differenceBy(arr2, arr, 'id'))
  }
})

const result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
      .with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }])

console.log(result) 
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script> 

Вы можете заменить / добавить в одном цикле, объединив оба массива, сведя их к карте и просто добавив элементы id на карту:

 const mergeById = arr => ({
  with(arr2) {
    return Array.from(
      [...arr, ...arr2]
        .reduce((r, o) => r.set(o.id, o), new Map)
        .values()
    )
  }
})

const result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
      .with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }])

console.log(result) 
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script> 

Комментарии:

1. Почему два ? ?

2. будьте более конкретными

3. Извините, в вашем коде было два вопросительных знака. Похоже, вы отредактировали его сейчас. Спасибо

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