0

I have the following Arrays:

this.originalSelectedRows = [1,2,3,4,5];
this.selectedRows = [3,4,5,6,7,8];

I want to know the following:

How many numbers are in this.originalSelectedRows, but not in this.selectedRows

Which in this case would be 2:

1 and 2

and how many numbers are in this.selectedRows, but not this.originalSelectedRows

Which in this case would be 3:

6, 7 and 8

I have the following, which works fine:

    let isOnListCount = 0;
    let isNotOnListCount = 0

    this.selectedRows.map((row) => {
      const isSelected = this.originalSelectedRows.filter(x => x === row);
        if(isSelected.length > 0)
          isOnListCount++;
        else
          isNotOnListCount++;
    });

But I want to know if this can be achieved in a neater fashion usng some of ES6's new features, or original JS

Alex
  • 3,391
  • 5
  • 36
  • 79

4 Answers4

2

You could take the length as counter and reduce the value with common items.

var array1 = [1, 2, 3, 4, 5],
    array2 = [3, 4, 5, 6, 7, 8],
    count1 = array1.length,
    count2 = array2.length;
    
array1.forEach(function (a) {
    if (array2.includes(a)) {
        count1--;
        count2--;
    }
});
console.log(count1, count2);
Nina Scholz
  • 351,820
  • 24
  • 303
  • 358
  • Readability is more important than short fancy code. You always have a way of making the most simple logic completely incomprehensible to new programmers. – Cerbrus Oct 13 '17 at 13:15
  • Specifically `&& (count1--, count2--)` is something new users will not recognize. `&&` as shortcut `if` and the `( , )` aren't common structures that they will recognize. – Cerbrus Oct 13 '17 at 13:26
  • @NinaScholz I know how much you wanted to use `reduce`, and write more obscure code. Here you go: `const common = arr.reduce((result, elt) => result + array2.includes(elt));`. Note the clever way we add a boolean. Now the answers are simply `array1.length - common` and `array2.length - common`. –  Oct 13 '17 at 17:09
  • @torazaburo, you know (i hope so), that i am able to write that in reduce style, but it is not necessary in this case (for saving a single line of code). – Nina Scholz Oct 13 '17 at 21:56
1

Sets will do a great job here :)

let set1 = new Set(this.originalSelectedRows)
let set2 = new Set(this.selectedRows)
let difference = new Set([...set1].filter(n => !set2.has(n)))

They are also relatively fast as well, but not as fast as a specially crafted solution :P

I am assuming that all of your items are unique though :)

user2662833
  • 933
  • 1
  • 8
  • 19
1

I'd convert one array into a set and than filter the other array for items which aren't in the set.

const
  valuesA = [1,2,3,4,5],
  valuesB = [3,4,5,6,7,8];
  
function getUniqueValues(sourceArray, testArray) {
  const 
    set = new Set(testArray);
    
  return sourceArray.filter(value => !set.has(value));
}

console.log(`Values in A and not in B: ${getUniqueValues(valuesA, valuesB)}`);
console.log(`Values in B and not in A: ${getUniqueValues(valuesB, valuesA)}`);
Thijs
  • 2,321
  • 2
  • 13
  • 21
0

You can just use Array#includes function to check if the element exists in the second array or not

const originalSelectedRows = [1,2,3,4,5];
const selectedRows = [3,4,5,6,7,8];

let isOnListCount = 0;
let isNotOnListCount = 0;

selectedRows.forEach(row => 
 originalSelectedRows.includes(row) ? isOnListCount++ : isNotOnListCount++
);

console.log(isOnListCount);
console.log(isNotOnListCount);
Suren Srapyan
  • 62,337
  • 13
  • 111
  • 105
  • @Alex You've accepted an answer which gives an answer different from that you yourself said was correct, which was a `2` for the first case. –  Oct 13 '17 at 16:45
  • You are right. I am going to remove this answer. I didn't notice that my result is wrong. Remove the acceptance, to let me remove this – Suren Srapyan Oct 13 '17 at 16:51
  • Why don't you just fix the answer, instead of deleting it? – Cody Gray Oct 14 '17 at 13:00