【问题标题】:How can I select a unique element in the array?如何选择数组中的唯一元素?
【发布时间】:2019-10-29 15:09:53
【问题描述】:

我正在尝试解决在数组中查找唯一元素的任务。 到目前为止,我设法解决了 95%,但我在 0 上失败了。我收到一条错误消息,说预期为 0 并得到 1。

我应该得到 //10,确实如此,但是在我在线测试失败之后。对于所有其他已通过的值。

关于如何解决这个问题以及我在这里缺少什么的任何想法?

function findOne(arr) {
  let x = arr[0];
  for (let i of arr) {
    if (i === x) {
      continue;
    } else {
      x = i;
    }
    return x;
  }
}
console.log(findOne([3, 10, 3, 3, 3]));

【问题讨论】:

  • 因为你设置了 x,所以用所有的 3 来测试它
  • 如果您需要数组中的唯一元素,reduce 将是一种更简洁的方法
  • 如果你不打你的continue,你总是打return
  • 不,只有一个int...

标签: javascript arrays sorting unique element


【解决方案1】:

我真的不明白你的代码。你从数组中的第一个值开始,然后循环遍历数组,跳过任何相同的值,然后返回第一个不同的值。那不会找到唯一值,它只会找到不等于第一个值的第一个值。因此,例如,在数组 [1,2,2,2,2] 上尝试它,您将得到 2 而不是 1 的结果,即使这显然是错误的。

相反,您可以创建每个值及其发生率的映射,然后按末尾等于 1 的值进行过滤。

function findOne(arr) {
    const incidences = arr.reduce((map, val) => {
      map[val] = (map[val] || 0) + 1;
      return map;
    }, {});
    const values = Object.keys(incidences);
    for (let i = 0; i < values.length; ++i) {
      if (incidences[values[i]] === 1) { return values[i]; }
    }
    return null;
}

EDIT 上面不会保留值的类型(即它总是将其转换为字符串,即使它最初是一个数字)。要保留类型,您可以使用实际的 Map 而不是对象:

function findOne(arr) {
    const incidences = arr.reduce((map, val) => {
      map.set(val, (map.get(val) || 0) + 1);
      return map;
    }, new Map());
    const singletons = Array.from(incidences).filter(entry => entry[1] === 1);
    return singletons.map(singleton => singleton[0]);
}

【讨论】:

  • 没问题,我只是想帮助您学习 :) 我还意识到我的原始代码会将所有值更改为字符串,因此我添加了另一个使用实际 Maps 来保留类型的版本。 (它返回一个包含所有唯一值的数组,如果没有,则返回一个空数组。)这个想法是,对于每个值,如果之前没有看到该值,则将该值的映射设置为 0,或者使用当前值;然后加 1。这将为您提供所有值的映射以及它们出现的频率;然后你寻找只出现一次的那个并返回它。
  • 它失败了......而且我理解你的代码也很复杂。通过考试不是最重要的。我也需要了解我的解决方案...
  • 它是如何失败的?我用输入数组 [0,1,1,2,2,3,3] 对其进行了测试,它返回了结果数组[0],这是正确的,因为 0 是唯一的重复值。 (我试图在之前的评论中解释代码;如果您对此有任何不明白的地方,请随时提问!:))
  • 它失败了:我得到:预期:1,而不是:[1] 预期:2,而不是得到:[2] 预期:10,而不是得到:[10] 信息不多,但是它没有通过......
  • 正如我所说,它返回一个唯一值数组(由它们周围的[] 括号表示);看起来测试只需要没有数组的值。所以你可以只返回结果的第一个数组元素而不是整个数组,它对于那些只有一个唯一值的情况可以正常工作。
【解决方案2】:

考虑以下几点:

回想一下span = max - min + 1;

Partition P1 变成span 来自0..span-1

Partition P2 变成span 来自span..(2*span)-1

如果P2 中没有,请在P1 中输入一个数字。

如果P2 已经在P1 中,则在P2 中放置一个数字。

一旦号码在P2不要再考虑了

如果一个数字在P1那么它是唯一的

【讨论】:

    【解决方案3】:

    您可以通过使用地图计算每个元素出现的次数来获取所有出现一次的值。然后,您可以将该映射缩减为一组唯一值:

    const findUnique = arr => {
      const mapEntries = [...arr.reduce((a, v) => a.set(v, (a.get(v) || 0) + 1), new Map()).entries()]
      return mapEntries.reduce((a, v) => (v[1] === 1 && a.push(v[0]), a), [])
    }
    
    console.log(findUnique([3, 10, 3, 3, 3]))
    console.log(findUnique([1, 2, 3, 2, 4]))
    console.log(findUnique([4, 10, 4, 5, 3]))

    如果你不关心多个唯一值,你可以只对数组进行排序并使用逻辑,而不是检查每个值,前提是数组只包含 2 个不同的值,并且长度大于 2:

    const findUnique = arr => {
      a = arr.sort((a, b) => a - b)
      if (arr.length < 3 || new Set(a).size === 1) return null
      return a[0] === a[1] ? a[a.length-1] : a[0]
    }
    
    console.log(findUnique([3, 10, 3, 3, 3]))
    console.log(findUnique([3, 3, 1]))
    console.log(findUnique([3, 1]))
    console.log(findUnique([3, 3, 3, 3, 3]))

    【讨论】:

    • 您应该记录您的代码。您介绍了许多 OP 不一定理解的新概念(reduceSetMap 等)。
    • 这个做到了,但是理解所有变量对我来说是相当先进的......你能在排序后的数组之后一步一步解释吗?
    • @TiagoRuivo 你用的是哪个版本的?我会尽力解释的。
    • 第二个......也许如果你澄清你的代码以获得更简单的JS。更具描述性的...
    • @TiagoRuivo 首先,我对数组进行排序,使它们都按顺序排列,顺序无关紧要,只要重复项彼此相邻即可。例如 [2, 3, 2] 将排序为 [2, 2, 3]。然后我们检查第一个值是否等于第二个值。我们知道如果它相同,那么最后一个值将是唯一值,因为只有两种不同类型的值。否则,如果前两个不同,则第一个值是非重复值。 if 语句 is to check 是检查数组是否长于 2 个元素,这是必须的,否则两者都可能是唯一的。
    【解决方案4】:

    你的代码很复杂,试试这个

    function findOne(arr) {
      const uniqueItems = [];
      arr.forEach(item => {
        const sameItems = arr.filter(x => x === item);
        if (sameItems.length === 1) {
          uniqueItems.push(item);
        }
      });
    
      return uniqueItems;
    }
    console.log(findOne([0, 1, 1, 3, 3, 3, 4]));
    

    我正在从传递的数组中获取所有唯一项,它可能有多个唯一项

    【讨论】:

    • 它也没有通过...它比我的解决方案更失败...我只有一个独特的 int ...
    • @TiagoRuivo 我刚刚测试过,它确实有效;它返回一个唯一值的数组。如果您只想检查一个,则可以获取结果的第一个条目。
    • 虽然这有效,但 forEach 中的过滤器意味着它以 O(n^2) 的效率运行,这比它需要的要慢得多......
    • 这是任务:有一个带有一些数字的数组。除了一个,所有数字都相等。试着找到它! findUniq([ 1, 1, 1, 2, 1, 1 ]) === 2 findUniq([ 0, 0, 0.55, 0, 0 ]) === 0.55 保证数组包含3个以上的数字。跨度>
    【解决方案5】:

    这是一种更简单快捷的方式:

    function findOne(arr) {
      const a = arr.reduce((acc, e) => {
        e in acc || (acc[e] = 0)
        acc[e]++
        return acc
      }, {})
      return Object.keys(a).filter(k => a[k] === 1)[0] || null
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-19
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 2020-03-20
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      相关资源
      最近更新 更多