51

Is there a way to return the missing values of list_a from list_b in TypeScrpit?

For example:

var a1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var a2 = ['a', 'b', 'c', 'd', 'z'];

The result value is

['e', 'f', 'g'].
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Galma88
  • 2,398
  • 6
  • 29
  • 50
  • 1
    So you would like to compare a1 and a2 and check which is missing in a2 and print them or add them in a2? I'm not sure if I understood it right.. – webta.st.ic Jul 21 '16 at 07:59
  • I need element missing in a1 from a2 but I don't need element missing in a2 from a1. – Galma88 Jul 21 '16 at 08:18

6 Answers6

94

There are probably a lot of ways, for example using the Array.prototype.filter():

var a1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var a2 = ['a', 'b', 'c', 'd'];

let missing = a1.filter(item => a2.indexOf(item) < 0);
console.log(missing); // ["e", "f", "g"]

(code in playground)


Edit

The filter function runs over the elements of a1 and it reduce it (but in a new array) to elements who are in a1 (because we're iterating over it's elements) and are missing in a2.

Elements in a2 which are missing in a1 won't be included in the result array (missing) as the filter function doesn't iterate over the a2 elements:

var a1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var a2 = ['a', 'b', 'c', 'd', 'z', 'hey', 'there'];

let missing = a1.filter(item => a2.indexOf(item) < 0);
console.log(missing); // still ["e", "f", "g"]

(code in playground)

Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299
  • it seems good but ii shows also the values that I have in B and I don't have in A. but I don't need them. – Galma88 Jul 21 '16 at 08:15
  • It returns `["e", "f", "g"]` just like you wanted... So I'm not sure what you mean – Nitzan Tomer Jul 21 '16 at 08:17
  • I edited my question. If I have a 'z' in a2 your script return also the 'z' but I don't need it – Galma88 Jul 21 '16 at 08:19
  • No, my script will still return `["e", "f", "g"]` even with the added `z` to `a2`. even `var a2 = ['a', 'b', 'c', 'd', 'z', 'hey', 'there'];` it will still return the requested missing values, [check it here](https://www.typescriptlang.org/play/#src=var%20a1%20%3D%20%5B'a'%2C%20'b'%2C%20'c'%2C%20'd'%2C%20'e'%2C%20'f'%2C%20'g'%5D%3B%0D%0Avar%20a2%20%3D%20%5B'a'%2C%20'b'%2C%20'c'%2C%20'd'%2C%20'z'%2C%20'hey'%2C%20'there'%5D%3B%0D%0A%0D%0Alet%20missing%20%3D%20a1.filter(item%20%3D%3E%20a2.indexOf(item)%20%3C%200)%3B%0D%0Aconsole.log(missing)%3B%20%2F%2F%20%5B%22e%22%2C%20%22f%22%2C%20%22g%22%5D). – Nitzan Tomer Jul 21 '16 at 08:22
  • That's perfect, thant you. I just wrote this little "array diff" function for anyone interested: const arrayDiffs = (oldArray: any[] = [], newArray: any[] = []) => { const added = newArray.filter((item) => oldArray.indexOf(item) < 0); const removed = oldArray.filter((item) => newArray.indexOf(item) < 0); return { added, removed }; }; – oiawo Aug 23 '20 at 11:06
  • What about performance ? a1.filter(item => a2.indexOf(item) < 0) is just a nested loop in disguise. Isn't there a solution that uses Sets ? – Cesar Feb 01 '21 at 14:12
  • This handles type well: arrayDifference(total: T[], toSubtract: T[]): T[] { return total.filter(item => toSubtract.indexOf(item) < 0); } – Polyterative Nov 11 '21 at 09:19
16

Typescript only provides design / compile time help, it doesn't add JavaScript features. So the solution that works in JavaScript will work in Typescript.

Plenty of ways to solve this, my goto choice would be lodash: https://lodash.com/docs#difference

_.difference(['a', 'b', 'c', 'd', 'e', 'f', 'g'],['a', 'b', 'c', 'd']);
Ross Scott
  • 1,690
  • 9
  • 16
9

You can only use this method. With the larger table first.

const a1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
const a2 = ['a', 'b', 'c', 'd', 'x', 'y', 'z'];

const difference_a1 = a1.filter(x => !a2.includes(x));

const difference_a2 = a2.filter(x => !a1.includes(x));

console.log(difference_a1);
/* ["e","f","g"] */

 console.log(difference_a2);
/* ["x","y","z"] */
Fisherman
  • 147
  • 1
  • 5
4

You can look for both values:

const removed = before.filter((x: any) => !after.includes(x));
const added = after.filter((x: any) => !before.includes(x));
Jonathan
  • 3,893
  • 5
  • 46
  • 77
0
const a1 = ['a', 'b', 'c', 'd', 'e', 'f'];
const a2 = ['a', 'b', 'c'];
     
let bigArray = null;
let smallArray = null;
if(a1.length >= a2.length)
  {
    bigArray = a1;
    smallArray =a2;
  } else {
    bigArray= a2;
    smallArray =a1;
  }       
const diff = bigArray.filter(item => smallArray.indexOf(item) < 0); 
console.log(diff);
Sonu
  • 25
  • 8
0

Why don't leverage the power of Javascript :-)

var a1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var a2 = ['a', 'b', 'c', 'd', 'k', 'l', 'M', 'j'];
let difference: string[] = [];
difference = difference.concat(a1.filter(item => a2.indexOf(item) < 0))
.concat(a2.filter(item => a1.indexOf(item) < 0));

or 

difference = difference.concat(a1.filter(item => !a2.include(item)))
.concat(a2.filter(item => !a1.include(item)));


console.log(difference); // ["e", "f", "g", "k", "l", "M", "j"]
mahig
  • 151
  • 1
  • 3