【问题标题】:Javascript code help - Wrong returnJavascript 代码帮助 - 错误返回
【发布时间】:2013-01-23 18:44:59
【问题描述】:

所以我正在编写这个脚本。当我完成它时,它应该用于制作 2-and-2 组。但无论如何;脚本开头的“输入”数组将从我的 HTML 文件中获得 22 个不同的输入。作为标准,我给他们的值是 1-22。问题是我的两个块“第一个数字”和“第二个数字”效果不佳:它们没有返回正确的数字。因为我希望每个 elev[x] 都使用一次!不是2次,不是0次,一次!并且这些块像其中一些一样返回两次,其中一些甚至没有被使用。那么我该如何解决呢?

    function Calculate(){
    var elev = [];
    var inputs = document.getElementsByName("txt");
    for(i=0; i<inputs.length; i++) {
    elev[i] = {
        "Value": inputs[i].value,
        "Used": false
    };
}

    function shuffle(elev){
    var len = elev.length;
    for(i=1; i<len; i++){
        j = ~~(Math.random()*(i+1)); 
        var temp = elev[i];
        arr[i] = elev[j];
        arr[j] = temp;
        }
    }

    for(var v=0; v<1; v++) {
        shuffle(elev);
        document.write(elev + '<br/>\n');
    }}

是的,我还是个编程新手,我只想学习我能学到的东西。

问题通过费雪-耶茨洗牌解决。

【问题讨论】:

  • elev[r] = elev[a]; elev[a] = elev[r]; 不会交换两个元素。首先,它将elev[a] 分配给elev[r](丢失elev[r] 的值),然后将相同的值分配回elev[a]
  • 为什么shuffle 有一个循环?我使用循环生成多个随机播放(以证明它是随机的),但我的印象是您只需要一个。
  • 不要使用document.write。使用 DOM 操作或至少 document.body.innerHTML +=
  • 此外,除非您实现 toString,否则对象不会完全转换为字符串,因此打印对象数组不会有任何好处。

标签: javascript loops if-statement


【解决方案1】:

改组数组并对其进行迭代的想法是正确的,但是,通过掷硬币比较器进行排序(常见的错误实现;由另一个答案提出)是不是正确的方法洗牌一个数组;它会产生非常扭曲的结果,甚至不能保证完成。

除非您愿意获取 underscore.js (arr = _.shuffle(arr)),否则建议使用 Fisher-Yates shuffle:

function shuffle(arr){
  var len = arr.length;
  for(var i=1; i<len; i++){
    var j = ~~(Math.random()*(i+1)); // ~~ = cast to integer
    var temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
  }
}

...

shuffle(elev);
for(var i=0; i<elev.length; i++){
  //do something with elev[i]
  console.log(elev[i].Value);
}

另外,请注意对象字段应该是小写,而不是大写(value', not 'Value'). Also, theUsed` 字段不应该是必需的,因为您现在按顺序迭代。此外,您是否有机会使用值数组?它们似乎是对象中的唯一字段。

另外,不要使用 document.write()。在页面加载后使用时,它不能按预期工作。如果你想在文档中附加一些东西,你讨厌 jQuery 和其他框架并且你不想走很长的路来创建和组合 DOM 节点,document.body.innerHTML += 仍然比document.write() 好(但仍然考虑附加 @ 987654328@s 代替')。

演示:http://jsfiddle.net/honnza/2GSDd/1/

【讨论】:

  • 我只是对一些事情感到困惑。什么是 temp(如果没有简短答案,请删除链接),'i' 和 'j' 索引呢?我可以复制/粘贴上面的脚本吗?
  • @Jan 你忘了var 你的ij 并且洗牌通常是向下而不是向上进行的,但似乎工作正常。我很少看到其他人使用~~ 转换为整数!
  • @PaulS。允许向上计数,称为由内而外的方法。如果您想在洗牌的同时初始化数组,则使用它。感谢vars。
  • @user1994248 因为一旦您执行x = y,之前的x 值就会被覆盖,如果您还想执行y = x 来“交换”它们,x 现在是@ 987654338@,所以你告诉它y = y,这是没有意义的。相反,您引入了一个新变量来存储xtemporarily。现在,temp = x; x = y; y = temp;,一切都如您所愿。
  • @PaulS。有趣的是,~~x 在 chrome 中比 x|0 稍快:jsperf.com/number-cast
【解决方案2】:

你只会得到一次随机数,如果它们还没有被使用过,就会处理它们。

我建议对数组 (elev.sort(function() {return Math.random()-0.5})) 进行洗牌,然后在没有更多随机数的情况下迭代结果。

【讨论】:

  • [1,2,3,4,5].sort(Math.random)[5,4,3,2,1] 几乎100% 的时间.. 不是很随机。
  • 你的洗牌算法很糟糕,即使比较器按你预期的那样工作。
  • 哦,听起来很简单。将尝试这样做,看看它是否有效。完成后我会更新帖子。 编辑:那么,我应该使用它还是不使用它?
  • @Kolink Fisher-Yates shuffle: for(i in 0..len-1) swap(arr, i, random(0..i))
  • @JanDvorak 很好地注意到了这一点。我无法编辑,所以又来了(我会删除上一个以防止人们错误地复制)function shuffleArray(a) {var i = a.length, t, j; while (--i) t = a[i], a[i] = a[j = ~~(Math.random() * (i+1))], a[j] = t;}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 2011-10-30
  • 2012-10-04
  • 1970-01-01
  • 2011-12-04
  • 2014-07-03
  • 1970-01-01
相关资源
最近更新 更多