Слияние деревьев в Javascript без написания цикла - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть пара массивов, которые содержат отдельные объекты, как показано ниже.Я хотел бы объединить эти две структуры в одну:

Изменения

Массив изменений, определение которых:

{ 
  app_name: "App 1"
  2017: {fYear: 2017, changesCount: 37}, 
  2018: {fYear: 2018, changesCount: 10}
}

Проблемы

Массив проблем, определение которых

{ 
  app_name: "App 1",
  2018: {fYear: 2018, all: 10, typeA: 1, typeB:5, TypeC: 1}
}

Конечный результат

Поиск массива объединенных объектовкаждый объект - это слияние изменений и проблем:

{ 
  app_name: "App 1"
  2017: {fYear: 2017, changesCount: 37}, 
  2018: {fYear: 2018, changesCount: 10, all: 10, typeA: 1, typeB:5, TypeC: 1}
}

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

Любая рекомендация?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Я могу придумать несколько способов сделать это:

1) Используя Map на одном массиве (надмножество) и использовать Find inside, чтобы найти соответствующий элемент в другом массиве.Чтобы это работало, один массив должен быть надмножеством, а имя_приложения должно быть уникальным в обоих массивах.(Вы можете изменить поиск на фильтр, если имя_приложения не уникально)

2) Более общее: создайте карту объектов с ключами app_name и дополните поля из обоих массивов.

ПримерИспользование метода карты объектов

let changes = [{
  app_name: "App 1",
  2017: {
    fYear: 2017,
    changesCount: 37
  },
  2018: {
    fYear: 2018,
    changesCount: 10
  }
}]

let issues = [{
  app_name: "App 1",
  2018: {
    fYear: 2018,
    all: 10,
    typeA: 1,
    typeB: 5,
    TypeC: 1
  }
}]
/*
Expected Result:
{ 
  app_name: "App 1"
  2017: {fYear: 2017, changesCount: 37}, 
  2018: {fYear: 2018, changesCount: 10, all: 10, typeA: 1, typeB:5, TypeC: 1}
}*/

function merge(arr1, arr2) {

  // Keep an object to accumulate the keys onto
  const acc = {};

  // Helper to register array items on to the accumulator
  function registerToMap(array) {
    array.forEach(function(item) {
      let app_name = item.app_name;
      if (!acc[app_name]) {
        // This app_name is not in the accumulator yet
        // Delete this key to make sure our merge later does not operate on this key
        delete item.app_name;
        acc[app_name] = item;
        return;
      }

      // Merge inner keys of incoming object
      Object.keys(item).forEach(function(key) {
        acc[app_name][key] = Object.assign({}, acc[app_name][key], item[key])
      })
      
      
      // The above steps could be easier using a lib with a proper merge function
      // acc[app_name] = _.merge({}, item, acc[app_name])

    })
  }
  
  // Register the first array elements onto the accumulator
  registerToMap(arr1);
  
  // Register the second array elements onto the accumulator
  registerToMap(arr2);

  // Rebuild array
  return Object.keys(acc).map(function(key) {
    return Object.assign({}, acc[key], {
      app_name: key
    });
  })

}

console.log(merge(changes, issues))
0 голосов
/ 17 декабря 2018
let a = {
  app_name: "App 1",
  '2017': { fYear: 2017, changesCount: 37 },
  '2018': { fYear: 2018, changesCount: 10 }
}
let b = {
  app_name: "App 1",
  2018: { fYear: 2018, all: 10, typeA: 1, typeB: 5, TypeC: 1 }
}

let c = { ...a, ...b };
let d = Object.keys(c).reduce((result, item) => {
  if (a[item] && typeof a[item] === 'object') {
    Object.assign(result[item], a[item])
  }
  return result;
}, c);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...