【问题标题】:Check for duplicates in array with randomly generated values使用随机生成的值检查数组中的重复项
【发布时间】:2016-05-13 08:12:05
【问题描述】:

我正在处理练习题,并被困在一个基于 jasmine-node 的测试中,它说我应该能够生成 10000 个随机名称而不会发生任何冲突(例如 2 个随机生成的名称匹配)。这是测试:

it('there can be lots of robots with different names each', function() {

    var i,
    numRobots = 10000,
    usedNames = {};

    for (i = 0; i < numRobots; i++) {
      var newRobot = new Robot();
      usedNames[newRobot.name] = true;
    }

    expect(Object.keys(usedNames).length).toEqual(numRobots);

});

认为我需要做的是:

  1. 创建一个数组来保存所有名称 (robotNames),
  2. 每次生成名称时,检查是否存在于数组中,
  3. 如果是,生成另一个名称,
  4. 如果没有,请将其添加到数组中。

这是我目前的代码...

"use strict";

var robotNames = [];
var name;

var Robot = function() {
    this.name = this.generateName();
};

Robot.prototype.generateName = function() {

    var letters = "";
    var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    var numbers = "";
    var digits = "0123456789";

    // generate random characters for robot name...

    for( var i=0; i < 2; i++ ) {
        letters += alphabet.charAt(Math.floor(Math.random() *    alphabet.length));
    };

    for( var i=0; i < 3; i++ ) {
        numbers += digits.charAt(Math.floor(Math.random() * digits.length));
    };

    name = letters+numbers;

    // Loop through array to check for duplicates

    for(var i = 0; i < robotNames.length; i++) {
        if (name == robotNames[i]) {
            this.generateName();
            return;
        } else {
            robotNames.push(name);
        }
    }

    return name;
};

Robot.prototype.reset = function() {
     this.name = this.generateName();
};

module.exports = Robot;

测试失败并显示错误消息:“预期 9924 等于 10000。”

每次运行测试时,'9924' 数字都会略有不同。我认为这意味着 generateName 函数最终会生成 2 个匹配的随机名称。似乎我的检查重复项的循环没有运行,我不确定为什么。

我尝试了几个不同版本的循环,但都没有成功。所以我的问题是 a) 我的方法是否正确,我的循环语法有问题吗?或者 b) 我对如何在这里检查重复项有错误的想法吗?

感谢任何指点,谢谢。

【问题讨论】:

  • 试试这个:return this.generateName(); 而不是 this.generateName(); return。我打赌你在usedNames 中的名字是空的。
  • robotNames.length 可能有问题。试试for(var i = 0, len = robotNames.length; i &lt; len; i++) 而不是for(var i = 0; i &lt; robotNames.length; i++)
  • @Kenney - 是的,我不明白我必须在循环中返回 this.generateName(),尽管我只是把 this.generateName() 放了就可以运行这个函数。谢谢!
  • 它确实运行了函数,你理解正确 - 但是你的 Robot 构造函数会这样做(就像 Robot.reset 一样):this.name = this.generateName(); 所以你的测试会得到一个空值 newRobot.name .所以有 2 个问题 - 这个问题和 @Emile 指出的关于 for 循环的问题。

标签: javascript arrays for-loop duplicates


【解决方案1】:

问题出在这一点:

for(var i = 0; i < robotNames.length; i++) {
    if (name == robotNames[i]) {
        this.generateName();
        return;
    } else {
        robotNames.push(name);
    }
}

...如果没有一个名字不匹配,你可能只想推送你的名字。在这里,只要找到不匹配的 ONE,就将其添加到列表中。你想要更多类似的东西:

for(var i = 0; i < robotNames.length; i++) {
    if (name == robotNames[i]) {
        return this.generateName();
    }
}
robotNames.push(name);

(实际上,再加上您甚至没有返回对 this.generateName() 的递归调用,我不确定您的程序如何工作...)

【讨论】:

  • 谢谢,您的回答完美。是的,我不明白我必须在循环中返回 this.generateName() ,尽管我只是放 this.generateName() 会运行该函数。干杯!
【解决方案2】:

查找具有 Set 实现的库。 Collections.js 就是一个很好的例子。

集合的一个特性是它没有重复项。因此,当您向集合添加值时,它会查找重复项,然后在不存在重复项时添加该值。

【讨论】:

    猜你喜欢
    • 2016-04-13
    • 1970-01-01
    • 2016-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 2016-05-05
    相关资源
    最近更新 更多