Сравните два массива объектов и, если значение для определенного ключа отсутствует, добавьте объект с этим значением в массив - двумя способами - PullRequest
2 голосов
/ 04 апреля 2020

У меня есть один массив, в котором есть объекты, ключи которых соответствуют другому массиву объектов с такими же ключами, а значением для первого ключа является индекс месяца (0 = январь, 1 = февраль и т. Д. c .) и точки могут пересекать деление на год (a:10, a:11, a:0, a:1)

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

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

В
let arr1 = [{a:0, b:1},{a:1, b:3},{a:3, b:18},{a:4, b:2}]
let arr2 = [{a:10, b:2},{a:11, b:4},{a:0, b:8},{a:1, b:5},{a:2, b:1}]

arr1 отсутствуют объекты со значениями a 10, 11 и 2, которые существуют в arr2, а в arr2 отсутствуют объекты со значениями a 3 и 4, которые существует в arr1

* 101 8 * В итоге я хочу получить :
arr1 = [{a:10, b:0},{a:11, b:3},{a:0, b:1},{a:1, b:3},{a:2, b:0},{a:3, b:18},{a:4, b:2}]
arr2 = [{a:10, b:2},{a:11, b:4},{a:0, b:8},{a:1, b:5},{a:2, b:1},{a:3, b:0},{a:4, b:0}]

Теперь arr1 имеет новые предметы / объекты для a:10, a:11 и a:2 в то время как arr2 имеет новые элементы для a:3 и a:4, все из которых имеют значение b 0;

Я попытался нарисовать это на бумаге, чтобы логически увидеть что бы я делал физически, но я просто не могу обдумать это, так что ответ «Для чайников» был бы действительно полезен. Я думал, что научился достаточно, чтобы быть пригодным для работы, но это действительно бросает меня в глаза, и это просто для простого HTML5 холстового графика. Я получаю данные из БД для сравнения двух строк на одном графике, где может не быть данных за один месяц для одного типа данных, но есть для другого типа данных. И для тех пятен, которые не существуют ни в одном, ни в другом, я хочу опустить линию до 0 на оси Y, а затем вернуться к следующему значению. https://github.com/rmgreenstreet/custom-forms/blob/master/public/javascripts/canvasRender.js

Ответы [ 4 ]

2 голосов
/ 04 апреля 2020

Наличие только месячных индексов не подходит для правильной сортировки. Просто добавьте информацию о году, и это будет легко сделать. Без сортировки это может выглядеть следующим образом:

// loop elements of the arr2 with reduce,
// if there is any element in arr1 with the same value of key 'a', 
// result is the same as on the previous step
// if there is no elements of that kind, add new object {'a': arr2['a'], 'b' : 0} into arr1

function newArray (arr1, arr2) {
  return arr2.reduce((result, obj2) => {
    if (arr1.some(obj1 => obj1['a'] === obj2['a'])) {
      return result;
    }
    return [...result, {['a'] : obj2['a'], 'b':0}];
  }, arr1)
}
// now you can assign the result of newArray() to new variables
const arr1_ = newArray(arr1, arr2)
const arr2_ = newArray(arr2, arr1)

конечная рабочая функция OP (изменив значение a на mm/yyyy string:

function equalize(arr1, arr2) {
    let newArr = arr2.reduce(function (result, obj2) {
        if (arr1.some(obj1 => obj1['a'] === obj2['a'])) {
            return result;
        }
        return [...result, {'a' : obj2['a'], 'b':0}];
    }, arr1);
    newArr.sort(function (a, b) {
        console.log(`a: ${a}`)
        a = a.x.split('/');
        b = b.x.split('/')
        return new Date(a[1], a[0], 1) - new Date(b[1], b[0], 1)
    });
    return newArr;
};
1 голос
/ 04 апреля 2020

Основная неприятность этой задачи - проверка наличия предметов с определенными значениями a. Наивное прямолинейное решение потребовало бы итерации по arr2 для каждого элемента arr1 и наоборот, что делает его O (n 2 ), т.е. медленным.

Альтернативный подход предполагает использование объектов в качестве карт быстрого поиска. Идея состоит в том, чтобы вывернуть ваш массив наизнанку, использовать a s в качестве ключей и b s в качестве значений.

let arr1 = [{a:1, b:1},{a:2, b:3},{a:4, b:18},{a:5, b:2}]
let arr2 = [{a:2, b:2},{a:3, b:4},{a:4, b:8},{a:6, b:5},{a:7, b:1}]

// Using objects as lookup maps.
let m1 = {}
let m2 = {}

// Filling the maps.
// The 'a' becomes a key, the 'b' becomes a value.
arr1.forEach(v => m1[v.a] = v.b)
arr2.forEach(v => m2[v.a] = v.b)

// Iterating over the keys of m1, checking if m2 has that key,
// if not - adding it with a value of 0.
for (let f in m1) m2[f] || (m2[f] = 0)

// The same goes for m2 -> m1.
for (let f in m2) m1[f] || (m1[f] = 0)

// At this point both m1 & m2 have all the keys from both arrays without gaps.

let res1 = []
let res2 = []

// Assembling the resulting arrays.
for (let f in m1) res1.push({a: f, b: m1[f]})

for (let f in m2) res2.push({a: f, b: m2[f]})

Извините, я склонен к однострочности.

0 голосов
/ 04 апреля 2020

Вот мое решение. Я использую loda sh для вспомогательных функций.

function combineArrays (a, b) {
  Object.keys(b).forEach(function (k) {
    const key = parseInt(k);
    if (!a[key]) {
      a[key] = b[key];
      a[key].b = 0;
    }
  });

  return _.values(a);
}

Фрагмент рабочего кода

// const arr1 = [{ a: 1, b: 1 }, { a: 2, b: 3 }, { a: 4, b: 18 }, { a: 5, b: 2 }];
// const arr2 = [{ a: 2, b: 2 }, { a: 3, b: 4 }, { a: 4, b: 8 }, { a: 6, b: 5 }, { a: 7, b: 1 }];

let arr1 = [{a:0, b:1},{a:1, b:3},{a:3, b:18},{a:4, b:2}]
let arr2 = [{a:10, b:2},{a:11, b:4},{a:0, b:8},{a:1, b:5},{a:2, b:1}]

const arr1Map = _.keyBy(arr1, 'a');
const arr2Map = _.keyBy(arr2, 'a');

function combineArrays(a1Map, a2Map) {
  const a = _.cloneDeep(a1Map);
  const b = _.cloneDeep(a2Map);

  Object.keys(b).forEach(function(k) {
    const key = parseInt(k);
    if (!a[key]) {
      a[key] = b[key];
      a[key].b = 0;
    }
  });

  return _.values(a);
}

console.log(combineArrays(arr1Map, arr2Map));
console.log(combineArrays(arr2Map, arr1Map));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
0 голосов
/ 04 апреля 2020

Вы должны пройти l oop через первый массив и проверить, есть ли каждый ключ во втором массиве. Если это не так, вы должны вставить элемент, используя arr.splice () .

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

let j = 0;
for (let i = 0; i < arr1.length; i++) {
  let possiblyMissingKey = arr1[i].a;
  while (arr2[j].a < possiblyMissingKey && j < arr2.length)
    j++;
  if (arr2[j].a != possiblyMissingKey) {
    let itemToInsert = {a:possiblyMissingKey, b:0};
    arr2.splice(j, 0, itemToInsert);
  }
}

После того, как вы пройдете через первый массив go, выполните второй массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...