Самый быстрый способ увидеть добавленные, удаленные и измененные объекты (не примитивы) между двумя массивами - PullRequest
0 голосов
/ 15 февраля 2020

У меня есть полностью ручной, уродливый способ найти все добавленные, удаленные и измененные объекты (не примитивы) между двумя массивами, и мне интересно, есть ли более быстрый и эффективный способ выполнить sh таким же предмет. Какие-нибудь библиотеки, которые совершают это sh? функция loda sh difference сообщает мне все различия, а не то, какие из них были добавлены, а какие изменены, поэтому она не выполняет то, что мне нужно.

Вот мой код. Это работает, и я хочу сделать именно это, просто самый эффективный способ:

    let previousState = state[0]; //<-- an array of object literals
    let currentState = state[1]; //<-- an array of object literals

    let added = [];
    let removed = [];
    let edited = [];

    for(let i = 0; i < previousState.length; i++){
        let old = previousState[i];
        let current = currentState.find(x => x.id === old.id);
        if(!current){
            removed.push(current);
        }
    }

    for(let i = 0; i < currentState.length; i++){
        let current = currentState[i];
        let old = previousState.find(x => x.id === current.id);
        if(!old){
            added.push(current);
            continue;
        }
        if(!_.isEqual(current, old)){ //<-- this is the lodash .isEqual function
            edited.push(current);
        }
    }

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Из того, что я измерил, это более чем в два раза быстрее, чем оригинальный алгоритм.

let control = {};
state[0].forEach(s => {
  control[s.id] = s;
});

let added = [];
let edited = [];

state[1].forEach(s => {
  if (control[s.id]) {
    if (!_.isEqual(control[s.id], s)) {
      edited.push(s); 
    }
    delete control[s.id];
  } else {
    added.push(s);
  }
});

let removed = Object.values(control);
1 голос
/ 20 февраля 2020

Это не обязательно быстрее во время выполнения, но делает его немного более «функциональным». Надеюсь, это поможет.

// You just need to rename the "a" and "b" variables to your variable names where "a" is the original array and "b" is the array that you're comparing to it.
const a = [{ id: 1, name: 'a' }, { id: 2, name: 'b' }];
const b = [{ id: 1, name: 'abc' }, { id: 3, name: 'c' }];

const removedFromA = _.differenceBy(a, b, 'id');
const addedToA = _.differenceBy(b, a, 'id');
const changedInA = _.chain(a)
	.reject((v) => _.find(removedFromA, { id: v.id }) || _.find(addedToA, { id: v.id }))
  .reject((v) => _.chain(b).find({ id: v.id }).isEqual(v).value())
  .value();

console.log('Removed From A: ', removedFromA);
console.log('Added To A: ', addedToA);
console.log('Changed In A: ', changedInA);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
...