从两个数组返回唯一元素

时间:2018-07-17 19:49:29

标签: javascript arrays object merge greedy

我有两个数字数组,我希望得到它们出现在两个数组中的唯一数字。然后我还要从两个数组中返回唯一数字。

例如:

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]

这是我的解决方案,它可以工作,但是我无法想到如何优化我的解决方案。仅使用JavaScript,就没有像loadash这样的工具。有什么想法吗?:

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)

3 个答案:

答案 0 :(得分:1)

您可以使用Array#includes代替Array#indexOf,因为它返回的是布尔值而不是索引。

要获得差异,您可以按两个数组的唯一值进行过滤(与原始数组相比,这产生的集合较小)。

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)

答案 1 :(得分:1)

我认为这种方法很好,只要它不会成为瓶颈。您正在执行三个O(n ** 2)操作来获取列表,所以如果有一种降低复杂度的方法,那就太好了。

您可以尝试的一件事是使用一个哈希表,该哈希表会保留看到该数字的次数。但是您需要稍微聪明一点,因为您不能只是数数,否则您将不知道1表示arr1还是arr2。但是,由于只有4种可能性,因此只需要2位即可表示它们。因此,当它在array1中时添加1,在array1中时添加2。这意味着1 in是arr1,2 in arr2和3都在。创建计数只是O(n + m),其中n和m是数组长度。 (不过,您仍然需要对此进行过滤,以获得最终结果)

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)

然后只需要使用类似的东西过滤您想要的东西:

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

答案 2 :(得分:0)

这是另一个版本。

此解决方案假定数组的长度相等。我们首先遍历数组并将值存储在2个字典中。这样可以消除在同一数组中发现的所有重复整数。然后,我们遍历其中一个字典,并检查是否在两个字典中都找到了密钥,然后从两个字典中删除该密钥。最后,我们从两个字典中获取剩余的键,并将它们存储为数组。

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));