How to increase count base on two array difference?

Viewed 64

I am trying to get a count from an initial value based on an old value to a new value change. Below example countA is the count of item 'a' in the array and countB is for b. I have an initial start of the count of countA and countB. Now lets say I had an old array which is const old1 = ['a']; which is now updated to const new1 = ['a', 'b'];, in this case it should increase the countA to 5. Again if I had const old2 = ['a']; const new2 = ['b']; this would change my countA to 3 and countB to 6;

I wrote something that works, but I was hoping with a better algorithm. Is there a better way to do this?

let countA = 4; let countB = 5;


  function arrayDiff(a, b) {
    return [
      ...a.filter(x => !b.includes(x)),
      ...b.filter(x => !a.includes(x))
    ];
  }

  function checkAndUpdateCount(oldVal, newBVal) {
    console.log('checkAndUpdateCount called ==========>');
    const difference = arrayDiff(oldVal, newBVal);
    console.log(difference);
    difference.forEach(item => {
      if (oldVal.includes(item) && newBVal.includes(item)) {
        console.log('no Changes');
      } else if (!oldVal.includes(item) && newBVal.includes(item)) {
        console.log(countA, countB);
        if (item === 'a') {
          countA++;
        } else {
          countB++;
        }
        console.log(countA, countB);
      } else if (oldVal.includes(item) && !newBVal.includes(item)) {
        console.log(countA, countB);
        if (item === 'a') {
          countA--;
        } else {
          countB--;
        }
        console.log(countA, countB);
      }
    });
  }

  const old1 = ['a']; const new1 = ['a', 'b'];
  const old2 = ['a']; const new2 = ['b'];
  const old3 = ['a', 'b']; const new3 = ['b'];
  const old4 = ['b', 'a']; const new4 = ['a'];
  const old5 = ['b', 'a']; const new5 = [];
  const old6 = []; const new6 = ['b', 'a'];

  checkAndUpdateCount(old1, new1); // this will return 4 6
  countA = 4; countB = 5;
  checkAndUpdateCount(old2, new2); // 4 6
  countA = 4; countB = 5;
  checkAndUpdateCount(old3, new3); // 3 6
  countA = 4; countB = 5;
  checkAndUpdateCount(old4, new4); // 4 4
  countA = 4; countB = 5;
  checkAndUpdateCount(old5, new5); // 3 4
  countA = 4; countB = 5;
  checkAndUpdateCount(old6, new6); // 5 6

https://jsfiddle.net/t3rvzn7f/1/

2 Answers

You could take an object for counting elements and iterate with a closure over the wanted value for updating the count.

This approach uses only two loops, one for every array.

function updateCount(oldA, newA) {
    const add = v => k => count[k] += v;
    oldA.forEach(add(-1));
    newA.forEach(add(1));
}

var count = { a: 0, b: 0 };

updateCount(['a'], ['a', 'b']);
console.log(count);

Here is a longer approach than the one proposed by Nina based on the same idea which illustrates some basic usage of math vectors teached in highschool..

You can do as you would in math with vectors, say in N^2

consider the vector CD

The difference is simply D-C.

Your initial point is [countA, countB]

The first component of C represents 'a' and second component represents 'b'.

So first thing: map your vector to a N^2 point:

let arrToPoint = v=>v.reduce((point, el)=>{
    point[el]++;
    return point;
},{a:0, b:0});

do the diff like you would for a vector

function diff(C, D){
    let v = {};
    Object.keys(D).forEach(k=>{
        v[k] = D[k]-C[k];
    });
    return v;
}

add the "diff" vector to your point

function update(point, v){
    Object.keys(v).forEach(k=>{
        point[k] += v[k];
    })
}

then your standard code

let arrToPoint = v=>v.reduce((point, el)=>{
    point[el]++;
    return point;
},{a:0, b:0});

function diff(C, D){
    let v = {};
    Object.keys(D).forEach(k=>{
        v[k] = D[k]-C[k];
    });
    return v;
}

function update(point, v){
    Object.keys(v).forEach(k=>{
        point[k] += v[k];
    })
}

function checkAndUpdateCount(old, next){
    let v = diff(arrToPoint(old), arrToPoint(next));
    update(X, v);
    console.log(X);
}
let X = {a:4, b:5}
const old1 = ['a']; const new1 = ['a', 'b'];
const old2 = ['a']; const new2 = ['b'];
const old3 = ['a', 'b']; const new3 = ['b'];
const old4 = ['b', 'a']; const new4 = ['a'];
const old5 = ['b', 'a']; const new5 = [];
const old6 = []; const new6 = ['b', 'a'];
checkAndUpdateCount(old1, new1); // this will return 4 6
X.a = 4; X.b = 5;
checkAndUpdateCount(old2, new2); // 4 6
X.a = 4; X.b = 5;
checkAndUpdateCount(old3, new3); // 3 6
X.a = 4; X.b = 5;
checkAndUpdateCount(old4, new4); // 4 4
X.a = 4; X.b = 5;
checkAndUpdateCount(old5, new5); // 3 4
X.a = 4; X.b = 5;
checkAndUpdateCount(old6, new6); // 5 6

note that you can do the diff and the update in one pass, just left it as is for illustration purpose

Related