Сравнение двух json-объектов и добавление недостающих элементов

383
22 марта 2017, 17:59

Есть два json-объекта с разным количеством элементов. В первом, допустим, 6 элементов с ключом segment, а во втором - 8. Можно ли как-то сравнить эти два json-объекта таким образом, чтобы алгоритм добавил к первому объекту 2 недостающих segment из второго? И насколько это ресурсо-затратно будет на клиенте?

Answer 1

Циклом пройти и добавить.
Для линейной асимптотики имеет смысл имеющиеся значения segment собрать предварительно.

let arr1 = [ 
  {seg: 1}, 
  {seg: 3}, 
  {seg: 5} 
]; 
 
let arr2 = [ 
  {seg: 1}, 
  {seg: 2}, 
  {seg: 4} 
]; 
// Собираем ключи из первого массива 
let seglist = arr1.reduce((o, el) => (o[el.seg] = true, o), {}); 
// Проходим по второму 
arr2.forEach(el => { 
  // Добавляем отсутствующие 
  if (!seglist[el.seg]) arr1.push(el); 
}); 
 
console.log(arr1)

Если уникального поля для этого нет(Вопрос), можно в качестве ключа использовать сериализованный объект: JSON.stringify(el).

Если объекты слишком велики - многократная сериализация может стать слишком накладной.
Можно попробовать другой алгоритм, с сортировкой (асимптотика не лучше О(nlogn)):

let arr1 = [{name: 'Alex', city: 'Chicago', position: 'Junior Dev'}, {name: 'John', city: 'Chicago', position: 'Middle Dev'}, {name: 'David', city: 'Chicago', position: 'Team Lead'} ]; 
let arr2 = [{name: 'Alex', city: 'Chicago', position: 'Junior Dev'}, {name: 'John', city: 'Chicago', position: 'Team Lead'}, {name: 'Den', city: 'Chicago', position: 'Team Lead'} ]; 
 
// Выбираем наиболее уникальное(имеющее большее количество уникальных значений поле), здесь это name 
 
// Группируем объекты по этому полю 
let objlist = arr1.reduce((o, el) => { 
    if (!o[el.name]) o[el.name] = []; 
    o[el.name].push(el); 
    return o; 
}, {}); 
 
const objEquals = (o1, o2) => { 
    // В общем случае, проверку здесь можно сделать более полной, например, если порядок ключей может различаться 
    return JSON.stringify(o1) === JSON.stringify(o2); 
} 
 
// Проходим по второму массиву 
arr2.forEach(el => { 
  // Добавляем отсутствующие 
  if (!objlist[el.name]) arr1.push(el); 
  else { 
    // Некто с таким же именем уже есть в первом массиве 
    for (let i = 0; i < objlist[el.name].length; ++i) { 
        let o = objlist[el.name][i]; 
        let exists = false 
         
        if (objEquals(o, el)) { 
            // Полное совпадение, выходим 
            exists = true; 
            break; 
        } 
        // Не нашли совпадения, дополняем первый массив 
        if (!exists) arr1.push(el); 
    } 
  } 
}); 
 
console.log(arr1);

Answer 2

Для Проверка двух массивов на идентичность

var array = [ 
    { name: 'Alex', city: 'Chicago', position: 'Junior Dev' }, 
    { name: 'John', city: 'Chicago', position: 'Middle Dev' }, 
    { name: 'David', city: 'Chicago', position: 'Team Lead' } 
]; 
 
var temp_array = [ 
    { name: 'Alex', city: 'Chicago', position: 'Junior Dev' }, 
    { name: 'John', city: 'Chicago', position: 'Middle Dev' }, 
    { name: 'Ben', city: 'Chicago', position: 'Senior Dev' }, 
    { name: 'David', city: 'Chicago', position: 'Team Lead' } 
]; 
 
function createLookup(input) { 
  var result = {}; 
   
  for(var i = 0; i < input.length; i++) { 
    var current = result; 
    for(var key in input[i]) { 
      if (!current[input[i][key]]) 
        current[input[i][key]] = {}; 
      current = current[input[i][key]]; 
    } 
  } 
   
  return result; 
} 
 
function existsInLookup(item, lookup) { 
  var current = lookup; 
  for (var key in item) { 
    //console.log(key); 
    //console.log(current[item[key]]); 
    if (!current[item[key]]) 
      return false; 
    current = current[item[key]]; 
  } 
  return true; 
} 
 
var lookup = createLookup(array); 
//console.log(lookup); 
for (var i = 0; i < temp_array.length; i++) { 
  var exists = existsInLookup(temp_array[i], lookup); 
  console.log(exists); 
  if (!exists) { 
    array.push(temp_array[i]); 
    console.log(temp_array[i]); 
  } 
}

READ ALSO
Как в Trampermonkey выбрать и кликнуть по options в select

Как в Trampermonkey выбрать и кликнуть по options в select

Очень бы хотелось, чтобы скрипт автоматом выбирал из выпадающего списка "Компьютеры"

362
react-hot-loader в Gulp

react-hot-loader в Gulp

Добрый день! Стоит задача писать проект на ReactJS в GulpПытаюсь найти хоть какую нибудь информацию по hot load для Gulp и пока ничего не нашел

268
Как отловить нажатие по кнопке: буквы, цифры, знаки препинания на любой раскладке

Как отловить нажатие по кнопке: буквы, цифры, знаки препинания на любой раскладке

Как обработать событие нажатия по кнопке, только если нажата буква или цифра, или знак препинания, при нажатии на русской или английской раскладке?

218
Определить выбранный option и запуск функции

Определить выбранный option и запуск функции

Как определить выбранный option по id и запустить привязанную к нему функцию? Может быть, можно вообще что-то наподобие onclick?

260