Return 来自两个数组的唯一元素

Return unique elements from two arrays

我有两个数字数组,我想要获取两个数组中出现的唯一数字。然后我还想 return 来自两个数组的唯一数字。

例如:

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)

您可以使用 Array#includes instead of Array#indexOf,因为它 returns 是一个布尔值而不是索引。

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

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)

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

您可以尝试的一件事是使用哈希 table 来记录数字被看到的次数。但是你需要有点聪明,因为你不能只数数,否则你不知道 1 是 arr1 还是 arr2。但是由于只有 4 种可能性,您只需要 2 位来表示它们。所以当它在 array1 中时你加 1,当它在 array1 中时你加 2。这意味着 1 是 arr1,2 是 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 个字典中。这消除了在同一数组中找到的任何重复整数。然后我们遍历其中一个字典并检查是否在两个字典中都找到了该键,然后从两个字典中删除该键。最后,我们从两个字典中获取剩余的键并将它们存储为数组。

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