Я хотел бы перейти от

var var1 = [
  {key:'key1',value1:'value11'},
  {key:'key2',value1:'value12'}
];

var var2 = [
  {key:'key1',value2:'value21'},
  {key:'key2',value2:'value22'}
];

Сюда

var var3 = [
  {key:'key1',value1:'value11',value2:'value21'},
  {key:'key2',value1:'value12',value2:'value22'}
];

Какой самый простой способ?

0
user310291 13 Янв 2017 в 06:11

4 ответа

Лучший ответ

Медленное решение

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

Это решение будет иметь постоянное пространство, но квадратичное время O(arr1.length) * O(arr2.length), потому что для каждого объекта в массиве 1 мы ищем совпадение в массиве 2.

var var1=[{key:"key1",value1:"value11"},{key:"key2",value1:"value12"}],var2=[{key:"key1",value2:"value21"},{key:"key2",value2:"value22"}];

// O(N*M) time, O(1) space
function mergeQuadratic(arr1, arr2) {
  const result = [];

  arr1.forEach(obj1 => {
    // try to find a match for the current arr1 object by searching through arr2
    const obj2 = arr2.find(obj2 => obj2.key === obj1.key);

    // if we found a match, we can merge these two objects
    if (obj2) {
      result.push(Object.assign({}, obj1, obj2));
    }
  });

  return result;
}

console.log(mergeQuadratic(var1, var2));

Версия ES5:

var var1=[{key:"key1",value1:"value11"},{key:"key2",value1:"value12"}],var2=[{key:"key1",value2:"value21"},{key:"key2",value2:"value22"}];

// O(N*M) time, O(1) space
function mergeQuadratic(arr1, arr2) {
  var result = [];
  arr1.forEach(function(obj1) {
    // try to find a match for the current arr1 object by searching through arr2
    var obj2 = arr2.find(function(obj2) {
      return obj2.key === obj1.key
    });

    // if we found a match, we can merge these two objects
    if (obj2) {
      result.push(Object.assign({}, obj1, obj2));
    }
  });

  return result;
}

console.log(mergeQuadratic(var1, var2));

Более быстрое решение

Улучшение для увеличения скорости состоит в том, чтобы компенсировать некоторое пространство и создать карту из массива 2, чтобы мы могли сократить время поиска соответствующего ключа, чтобы оно было постоянным, что дает нам линейное время выполнения O(array1.length) + O(array2.length) и линейное пространство {{X1} } :

var var1=[{key:"key1",value1:"value11"},{key:"key2",value1:"value12"}],var2=[{key:"key1",value2:"value21"},{key:"key2",value2:"value22"}];

// O(N+M) time, O(N) space
function mergeLinear(arr1, arr2) {
  // create a map of key->obj for every object in arr2
  const map = arr2.reduce((map, curr) => {
    map.set(curr.key, curr);
    return map;
  }, new Map());

  const result = [];

  arr1.forEach(obj1 => {
    // check almost instantly if a matching object exists
    const obj2 = map.get(obj1.key); // <-- Constant time lookup

    // if we found a match, we can merge these two objects
    if (obj2) {
      result.push(Object.assign({}, obj1, obj2));
    }
  });

  return result;
}

console.log(mergeLinear(var1, var2));

Версия ES5:

var var1=[{key:"key1",value1:"value11"},{key:"key2",value1:"value12"}],var2=[{key:"key1",value2:"value21"},{key:"key2",value2:"value22"}];

// O(N+M) time, O(N) space
function mergeLinear(arr1, arr2) {
  // create a map of key->obj for every object in arr2
  var map = arr2.reduce(function(map, curr) {
    map[curr.key] = curr;
    return map;
  }, Object.create(null));

  var result = [];

  arr1.forEach(function(obj1) {
    // check almost instantly if a matching object exists
    var obj2 = map[obj1.key]; // <-- Constant time lookup

    // if we found a match, we can merge these two objects
    if (obj2) {
      result.push(Object.assign({}, obj1, obj2));
    }
  });

  return result;
}

console.log(mergeLinear(var1, var2));
1
nem035 13 Янв 2017 в 04:00

Для хороших браузеров (не IE, но полифилы для Object.assign и для Array # find доступны)

var var3 = var1.map(function(o1) {
    return Object.assign({}, o1, var2.find(function(o2) {
       return o2.key === o1.key;
    }));
});

Или на современном языке

var var3 = var1.map(o1 => Object.assign({}, o1, var2.find(o2 => o2.key === o1.key)));
1
Jaromanda X 13 Янв 2017 в 03:29

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

Это решение не изменяет ни один из существующих массивов. Функция возвращает новый массив.

var var1 = [
  {key:'key1',value1:'value11'},
  {key:'key2',value1:'value12'}
];

var var2 = [
  {key:'key1',value2:'value21'},
  {key:'key2',value2:'value22'}
];


function mergeArrays(arr1, arr2) {
  var newArray = arr1;

  newArray.forEach(function (obj1) {
    arr2.forEach(function (obj2) {
      if (obj1.key === obj2.key) {
        obj1.value2 = obj2.value2;
      }
    });
  });

  return newArray;
}

var var3 = mergeArrays(var1, var2);

console.log(var3);
1
ppovoski 13 Янв 2017 в 03:29

Используя underscore.js (вы можете проверить это на консоли там)

Я оставлю это в качестве упражнения, чтобы сделать его однострочным, используя _.filter и _.map

function extendArrayByKey(var1, var2) {
  for (obj of var1) {
    var key = obj.key;
    for (obj2 of var2) {
      if (obj2.key == key) {
        _.extend(obj, obj2);
      }
    }
  }
}

Обратите внимание, что это изменило объекты в var1 с мелкими копиями значений в var2

1
OregonTrail 13 Янв 2017 в 06:05