Замена объектов в массиве

У меня есть этот объект JavaScript:

var arr1 = [{id:'124',name:'qqq'}, 
           {id:'589',name:'www'}, 
           {id:'45',name:'eee'},
           {id:'567',name:'rrr'}]

var arr2 = [{id:'124',name:'ttt'}, 
           {id:'45',name:'yyy'}]

Мне нужно заменить объекты в arr1 элементами из arr2 с тем же идентификатором.

Вот результат, который я хочу получить:

var arr1 = [{id:'124',name:'ttt'}, 
           {id:'589',name:'www'}, 
           {id:'45',name:'yyy'},
           {id:'567',name:'rrr'}]

Как я могу реализовать это с помощью JavaScript?

Ответ 1

Вы можете использовать Array#map с Array#find.

arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);

var arr1 = [{
    id: '124',
    name: 'qqq'
}, {
    id: '589',
    name: 'www'
}, {
    id: '45',
    name: 'eee'
}, {
    id: '567',
    name: 'rrr'
}];

var arr2 = [{
    id: '124',
    name: 'ttt'
}, {
    id: '45',
    name: 'yyy'
}];

var res = arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);

console.log(res);

Ответ 2

Поскольку вы используете Lodash, вы можете использовать _.map и _.find, чтобы убедиться, что поддерживаются основные браузеры.

В конце концов я бы пошел с чем-то вроде:

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:'45',name:'eee'},
           {id:'567',name:'rrr'}])
    .with([{id:'124',name:'ttt'}, {id:'45',name:'yyy'}])

console.log(result);
<script src="https://raw.githubusercontent.com/lodash/lodash/4.13.1/dist/lodash.js"></script>

Ответ 3

Если вам не нужен порядок массива, вы можете получить разницу между arr1 и arr2 на id, используя differenceBy(), а затем просто concat() добавить все обновленные объекты.

var result = _(arr1).differenceBy(arr2, 'id').concat(arr2).value();

var arr1 = [{
  id: '124',
  name: 'qqq'
}, {
  id: '589',
  name: 'www'
}, {
  id: '45',
  name: 'eee'
}, {
  id: '567',
  name: 'rrr'
}]

var arr2 = [{
  id: '124',
  name: 'ttt'
}, {
  id: '45',
  name: 'yyy'
}];

var result = _(arr1).differenceBy(arr2, 'id').concat(arr2).value();

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

Ответ 4

Я отправляю этот ответ только потому, что люди выражали беспокойство по поводу браузеров и поддержания порядка объектов. Я признаю, что это не самый эффективный способ достижения цели.

Сказав это, я разбил проблему на две функции для удобства чтения.

// The following function is used for each itertion in the function updateObjectsInArr
const newObjInInitialArr = function(initialArr, newObject) {
  let id = newObject.id;
  let newArr = [];
  for (let i = 0; i < initialArr.length; i++) {
    if (id === initialArr[i].id) {
      newArr.push(newObject);
    } else {
      newArr.push(initialArr[i]);
    }
  }
  return newArr;
};

const updateObjectsInArr = function(initialArr, newArr) {
    let finalUpdatedArr = initialArr;  
    for (let i = 0; i < newArr.length; i++) {
      finalUpdatedArr = newObjInInitialArr(finalUpdatedArr, newArr[i]);
    }

    return finalUpdatedArr
}

const revisedArr = updateObjectsInArr(arr1, arr2);

jsfiddle

Ответ 5

Благодаря ES6 мы можем сделать это простым способом → например на модуле util.js;))).

  1. Объединить массив 2 сущностей

    export const mergeArrays = (arr1, arr2) => arr1 && arr1.map(obj => arr2 && arr2.find(p => p.id === obj.id) || obj);

получает 2 массива и объединяет его. Arr1 является основным массивом, который является приоритетным высоко в процессе слияния

  1. Объединить массив с одним и тем же типом сущности

    export const mergeArrayWithObject = (arr, obj) => arr && arr.map(t => t.id === obj.id ? obj : t);

он объединяет тот же тип массива с каким-то типом для пример: массив person → [{id: 1, имя: "Bir"}, {id: 2, имя: "Iki"}, {id: 3, name: "Uc"}] второй параметр Person {id: 3, name: "Name изменен "} результат [{id: 1, имя:" Bir "}, {id: 2, имя:" Iki "}, {id: 3, имя: "Имя изменено"}]

Ответ 6

Что не так с Object.assign(target, source)?

enter image description here

Массивы по-прежнему являются объектами типа в Javascript, поэтому использование assign должно по-прежнему переназначать любые совпадающие ключи, анализируемые оператором, если найдены совпадающие ключи, верно?

Ответ 7

function getMatch(elem) {
    function action(ele, val) {
        if(ele === val){ 
            elem = arr2[i]; 
        }
    }

    for (var i = 0; i < arr2.length; i++) {
        action(elem.id, Object.values(arr2[i])[0]);
    }
    return elem;
}

var modified = arr1.map(getMatch);