FitTech
@FitTech

Как объединить массивы объектов так, чтобы в результирующем массиве значения определённого свойства были уникальны?

Есть три массива, первый это время, тут главное hours (car, bike - всегда нули).
Второй и третий массив это данные которые приходят порознь, два сразу только для примера.

let hours = [
	{ "hour":0, 'car':0, 'bike': 0},
	{ "hour":1, 'car':0, 'bike': 0},
	{ "hour":2, 'car':0, 'bike': 0},
	{ "hour":3, 'car':0, 'bike': 0},
	{ "hour":4, 'car':0, 'bike': 0},
	{ "hour":5, 'car':0, 'bike': 0},
	{ "hour":6, 'car':0, 'bike': 0},
	{ "hour":7, 'car':0, 'bike': 0},
];

let first = [
	{ "hour":5, 'car':10, 'bike': 10},
	{ "hour":8, 'car':20, 'bike': 0},
	{ "hour":9, 'car':30, 'bike': 0},
	{ "hour":10, 'car':40, 'bike': 0},
];

let second = [
	{ "hour":0, 'car':11, 'bike': 12},
	{ "hour":7, 'car':15, 'bike': 25},
	{ "hour":8, 'car':20, 'bike': 30},
	{ "hour":9, 'car':10, 'bike': 30},
	{ "hour":10, 'car':120, 'bike': 140},
];

Нужно объединить массив времени с другим массивом, добавив недостающие данные:

// hours + first
first = [
	// в first отсутствует hour:0,1,2,3,4, значит нужно добавить с массива hours
	{ "hour":0, 'car':0, 'bike': 0},
	{ "hour":1, 'car':0, 'bike': 0},
	{ "hour":2, 'car':0, 'bike': 0},
	{ "hour":3, 'car':0, 'bike': 0},
	{ "hour":4, 'car':0, 'bike': 0},
	// дальше добавляем то что было в first
	{ "hour":5, 'car':10, 'bike': 10},
	//  с hours, потому что в first нету 6,7
	{ "hour":6, 'car':0, 'bike': 0},
	{ "hour":7, 'car':0, 'bike': 0},
	{ "hour":8, 'car':20, 'bike': 0},
	{ "hour":9, 'car':30, 'bike': 0},
	{ "hour":10, 'car':40, 'bike': 0},
];

// hours + second:
second = [
	// Данные с second
	{ "hour":0, 'car':11, 'bike': 12},
	// Данные с hours
	{ "hour":1, 'car':0, 'bike': 0},
	{ "hour":2, 'car':0, 'bike': 0},
	{ "hour":3, 'car':0, 'bike': 0},
	{ "hour":4, 'car':0, 'bike': 0},
	{ "hour":5, 'car':0, 'bike': 0},
	{ "hour":6, 'car':0, 'bike': 0},
	// Данные с second должны затереть данные с нулями из hours
	{ "hour":7, 'car':15, 'bike': 25},
	{ "hour":8, 'car':20, 'bike': 30},
	{ "hour":9, 'car':10, 'bike': 30},
	{ "hour":10, 'car':120, 'bike': 140},
];
  • Вопрос задан
  • 1191 просмотр
Решения вопроса 3
0xD34F
@0xD34F Куратор тега JavaScript
Создаём новый массив:

const concat = (key, ...arrs) =>
  Object.values([]
    .concat(...arrs)
    .reduce((acc, n) => (acc[n[key]] = acc[n[key]] || n, acc), {})
  );


const newFirst = concat('hour', first, hours);

Дополняем существующий:

function add(key, target, ...sources) {
  const unique = new Set(target.map(n => n[key]));

  for (const arr of sources) {
    for (const n of arr) {
      const k = n[key];
      if (!unique.has(k)) {
        unique.add(k);
        target.push(n);
      }
    }
  }

  return target;
}


add('hour', first, hours).sort((a, b) => a.hour - b.hour); // да, придётся делать сортировку вручную
Ответ написан
sergiks
@sergiks Куратор тега JavaScript
♬♬
Тут ключевой индекс это hours. Поэтому стоит сначала переделать объекты в словари, где ключ час, а значение - объект с car и bike

Далее стоит определить минимальное и максимальное среди упомянутых значений часов – это диапазон, который надо будет покрыть подряд с шагом 1.

Далее двигаться по этому диапазону, наполняя данными из массива данных или дефолтного.

Потом привести опять к исходному формату, где ещё какие-то индексы в начале от 0.
Ответ написан
Комментировать
Immortal_pony
@Immortal_pony Куратор тега JavaScript
let hours = [
    {"hour":0, "car":0, "bike": 0},
    {"hour":1, "car":0, "bike": 0},
    {"hour":2, "car":0, "bike": 0},
    {"hour":3, "car":0, "bike": 0},
    {"hour":4, "car":0, "bike": 0},
    {"hour":5, "car":0, "bike": 0},
    {"hour":6, "car":0, "bike": 0},
    {"hour":7, "car":0, "bike": 0}
];

let first = [
    {"hour":5, "car":10, "bike": 10},
    {"hour":8, "car":20, "bike": 0},
    {"hour":9, "car":30, "bike": 0},
    {"hour":10, "car":40, "bike": 0}
];

let second = [
    {"hour":0, "car":11, "bike": 12},
    {"hour":7, "car":15, "bike": 25},
    {"hour":8, "car":20, "bike": 30},
    {"hour":9, "car":10, "bike": 30},
    {"hour":10, "car":120, "bike": 140}
];

function mergeArraysOfObjects(source, recepient, uniqueKey) {
    var result = [];

    source.forEach(function(sourceElement) { 
        var foundRecepientElement = null;
        recepient.forEach(function(recepientElement) { 
            if (recepientElement[uniqueKey] === sourceElement[uniqueKey]) {
                foundRecepientElement = recepientElement;
            }
        });

        if (foundRecepientElement !== null) {
            result.push(foundRecepientElement);
        } else {
            result.push(sourceElement);
        }
    });

    recepient.forEach(function(recepientElement) { 
        var foundSourceElement = null;
        source.forEach(function(sourceElement) { 
            if (sourceElement[uniqueKey] === recepientElement[uniqueKey]) {
                foundSourceElement = sourceElement;
            }
        });

        if (foundSourceElement === null) {
            result.push(recepientElement);
        }
    });

    return result;
}

var firstMerge = mergeArraysOfObjects(hours, first, 'hour');
var secondMerge = mergeArraysOfObjects(firstMerge, second, 'hour');

Пример
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы