1

Let, I have two arrays with strings.

let a = ["ABC", "DEF"]
let b = ["ABC", "DEF", "GHI"]

I want to compare the above two arrays and make a new array called c which contains the following.

c = ["GHI"]

So, I want to compare a and b arrays and push the non-identical elements into a new array.

How to do this in React Native?

Sennen Randika
  • 1,566
  • 3
  • 14
  • 34

3 Answers3

3

You can do that in following steps:

  • First get those elements of a which are not in b
  • Then get those elements of b which are not in a
  • Then concat() both the arrays.

let a = ["ABC", "DEF"]
let b = ["ABC", "DEF", "GHI"]

const res = a.filter(x => !b.includes(x)).concat(b.filter(x=> !a.includes(x)))
console.log(res)

How the code works

Consider the line

a.filter(x => !b.includes(x))

filter() is array method which takes a callback. If callback returns true then the element will be added to result array otherwise not.

So now in above code x is element of array b through which we are iterating. b.includes(x) will return true if x is present in array b otherwise false.

! operator converts true to false and vice verse

So if x will be inside b it will return true. So by ! it will be become false and false will be returned from callback. So the element x will not be included in result/filtered array.

The sentence for the line above line is that "It get only those items of array a which are not present in b"

The second line

b.filter(x=> !a.includes(x))

Gets those elements of b which are not in a.

Atlast concat() is used to join both array.

Community
  • 1
  • 1
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
  • Thank you so much for your answer. This solution perfectly works. Can you please explain me step-by-step how the line a.filter(x => !b.includes(x)).concat(b.filter(x=> !a.includes(x))) works? – Sennen Randika May 14 '19 at 06:20
  • 1
    @SennenRandika I have added a detailed explanation. Check it and if you don't understand something feel free to ask. – Maheer Ali May 14 '19 at 06:51
  • Perfect explanation!! Thank you so much for your answer and explanation. Used your answer and achieved what I wanted. Works perfectly. – Sennen Randika May 14 '19 at 10:28
2

You can also use Array.reduce and Array.filter like so:

const findUniques = (a,b) => [...a,...b].reduce((r,c,i,a) => {
  a.filter(x => x===c).length === 1 ? r.push(c) : null
  return r
}, [])

console.log(findUniques(["ABC", "DEF"], ["ABC", "DEF", "GHI"]))
console.log(findUniques(["ABC", "DEF"], ["ABC"]))
console.log(findUniques(["ABC", "DEF", "AAA"], ["AAA", "DEF", "GHI"]))

If you are using lodash this becomes really trivial with xor:

console.log(_.xor(["ABC", "DEF"], ["ABC", "DEF", "GHI"]))
console.log(_.xor(["ABC", "DEF"], ["DEF"]))
console.log(_.xor(["ABC", "DEF", "AAA"], ["AAA", "DEF", "GHI"]))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Akrion
  • 18,117
  • 1
  • 34
  • 54
  • Thank you for your answer!! This works!! Can you please explain me step-by-step how the line a.filter(x => x===c).length === 1 ? r.push(c) : null works? – Sennen Randika May 14 '19 at 06:30
  • 1
    Since we are using Array.reduce (a) is the actual input array we are reducing. So we are filtering inside of the reduce the main array to see which elements would be found ONLY once. Hence the `x===c`. Then those elements we push to the `accumulator r`. For those filtered values which have more than one hit we do nothing. Hence `null`. Hope this helps. – Akrion May 14 '19 at 06:34
  • its lifesaver lodash func thanx ! – cantaş Aug 18 '20 at 10:14
0

If you want to prevent going through the arrays O(n²) times, due to having to search each array for duplicate values, you could take advantage of the performance of JavaScript Objects.

const a = ["ABC", "DEF", "JKL"]
const b = ["ABC", "DEF", "GHI"]

const getUniqueValues = (a, b) => {
  const uniqueValuesObject = [...a, ...b].reduce((uniqueValuesObject, value) => {
    // if the value already exists, then it is not unique
    if (uniqueValuesObject[value]) {
      uniqueValuesObject[value] = false
    } else {
      uniqueValuesObject[value] = true
    }
    return uniqueValuesObject
  }, {})

  return Object.entries(uniqueValuesObject).reduce((uniqueValues, [value, isUnique]) => {
    if (isUnique) {
      uniqueValues.push(value)
    }
    return uniqueValues
  }, [])
}

const c = getUniqueValues(a, b)

console.log(c)

This can be shortened by using delete, however I am unsure if that will cause a performance hit compared to the solution above.

const a = ["ABC", "DEF", "JKL"]
const b = ["ABC", "DEF", "GHI"]

const getUniqueValues = (a, b) => {
  const uniqueValuesObject = [...a, ...b].reduce((uniqueValuesObject, value) => {
    // delete if the value already exists
    if (uniqueValuesObject[value]) {
      delete uniqueValuesObject[value]
    } else {
      uniqueValuesObject[value] = true
    }
    return uniqueValuesObject
  }, {})

  return Object.keys(uniqueValuesObject)
}

const c = getUniqueValues(a, b)

console.log(c)
Zaytri
  • 2,582
  • 2
  • 13
  • 19
  • Thank you for your answer!! What is the time complexity of the above solution? – Sennen Randika May 15 '19 at 02:17
  • @SennenRandika honestly, that depends on how `Objects` are implemented in whatever JavaScript engine you are using. For simplicity, if we assume that `Objects` are simply hash tables, then with the first solution it is possible to have an `Object` lookup of O(1), making the solution O(n) since all it does it traverse both arrays twice. Hash tables can have a worst time complexity of O(n) if many elements are hashed to the same key, which could give this O(n²) complexity, but it's unlikely. At the very least, it is much faster than searching the array using `filter`. – Zaytri May 15 '19 at 16:46
  • https://stackoverflow.com/questions/12241676/javascript-objects-as-hashes-is-the-complexity-greater-than-o1 – Zaytri May 15 '19 at 16:49