简体   繁体   中英

Return unique elements from two arrays

I have two arrays of numbers I want get get the unique numbers that appears in both arrays. Then I want to also return the unique numbers from both arrays.

For example:

INPUT:
let arr1 = [1234,4056,3045]
let arr2 = [5678,1234,5001]

OUTPUT:
only in arr1: [4056, 3045] 
only in arr2: [5678, 5001] 
in both lists: [1234]

Here is my solution, it works but I can't think of how optimize my solution. Just using JavaScript, no tools like loadash. Any thoughts?:

const getUniqueNumbers = (arr1, arr2) => {
  let uniqueOfBoth = arr1.filter((ele) => {
    return arr2.indexOf(ele) !== -1
  })

  let uniqueOfList1 = arr1.filter((ele) => {
    return arr2.indexOf(ele) == -1
  })

  let uniqueOfList2 = arr2.filter((ele) => {
    return arr1.indexOf(ele) == -1
  })

  return `Unique numbers from both list are ${uniqueOfBoth} 
              Unique nums to List1 : ${uniqueOfList1}
              Unique nums to List2 : ${uniqueOfList2}
    `
}

let result = getUniqueNumbers([1234, 4056, 3045], [5678, 1234, 5001])
console.log(result)

You could use Array#includes instead of Array#indexOf , because it returns a boolean value instead of the index.

For getting a difference, you could filter by the unique values of both arrays (this yields a smaller set, than to take the original arrays).

 const getUniqueNumbers = (arr1, arr2) => { let uniqueOfBoth = arr1.filter(ele => arr2.includes(ele)) let uniqueOfList1 = arr1.filter((ele) => !uniqueOfBoth.includes(ele)) let uniqueOfList2 = arr2.filter((ele) => !uniqueOfBoth.includes(ele)) return `Unique numbers from both list are ${uniqueOfBoth}\\nUnique nums to List1 : ${uniqueOfList1}\\nUnique nums to List2 : ${uniqueOfList2}` } let result = getUniqueNumbers([1234, 4056, 3045], [5678, 1234, 5001]) console.log(result) 

I think this approach is fine so long as it doesn't become a bottle neck. You are doing three O(n**2) operations to get your lists, so it could be nice if there was a way to reduce the complexity.

One thing you could try is to use a hash table that keeps count of how many times the numbers are seen. But you need to be a little clever because you can't just count otherwise you wouldn't know if 1 means arr1 or arr2 . But since there are only 4 possibilities you only need 2 bits to represent them. So you add 1 when it's in array1 and 2 when it's in array1. That means 1 in is arr1 , 2 in arr2 , and 3 is in both. Creating the counts is only O(n+m) where n and m are the array lengths. (You still need to filter that, however, to get your final result)

 const getUniqueNumbers =(arr1,arr2) =>{ let counter = {} arr1.forEach(i => counter[i] = counter[i] ? counter[i] + 1 : 1) arr2.forEach(i => counter[i] = counter[i] ? counter[i] + 2 : 2) return counter } let counts = getUniqueNumbers([1234,4056,3045],[5678,1234,5001]) console.log(counts) 

Then it's just a matter of filtering what you want with something like:

let both = Object.keys(counter).filter(key => result[key] === 3)

Here's another version.

This solution assumes the arrays are of equal length. We first iterate through the arrays and store the values in 2 dictionaries. This eliminates any duplicate integers found in the same array. We then iterate over one of the dictionaries and check if the key is found in both, then delete that key from both. Finally, we get the remaining keys from both dictionaries and store them as arrays.

const fn = (arr1, arr2) => {
  const obj = {
    arr1: [],
    arr2: [],
    both: []
  };
  const dict1 = {};
  const dict2 = {};

  for (let i = arr1.length; i--;) {
    dict1[arr1[i]] = true;
    dict2[arr2[i]] = true;
  }

  for (let key in dict1) {
    if (key in dict2) {
      obj.both.push(key);
      delete dict1[key];
      delete dict2[key];
    }
  }

  obj.arr1 = Object.keys(dict1);
  obj.arr2 = Object.keys(dict2);

  return obj;
}

const arr1 = [1234, 4056, 3045];
const arr2 = [5678, 1234, 5001];

console.log(fn(arr1, arr2));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM