javascript - 使用我用于随机化列表的 Javascript 代码的不同浏览器之间的结果不一致

标签 javascript sorting cross-browser

我从网站上获得了这段代码,用于随机化项目列表。 [这是一个音乐播放器,它在用户每次新访问时随机播放歌曲(列表),这样他们就不会因为从他们在过去访问时听到的同一首歌曲开始而感到无聊]

    $(document).ready(function(){
      $('ul').each(function(){
            // get current ul
            var $ul = $(this);
            // get array of list items in current ul
            var $liArr = $ul.children('li');
            // sort array of list items in current ul randomly
            $liArr.sort(function(a,b){
                  // Get a random number between 0 and 10
                  var temp = parseInt( Math.random()*10 );
                  // Get 1 or 0, whether temp is odd or even
                  var isOddOrEven = temp%2;
                  // Get +1 or -1, whether temp greater or smaller than 5
                  var isPosOrNeg = temp>5 ? 1 : -1;
                  // Return -1, 0, or +1
                  return( isOddOrEven*isPosOrNeg );
            })
            // append list items to ul
            .appendTo($ul);            
      });
});

当我在 Chrome 浏览器中打开我的网站时,这工作得很好。排序非常繁重,因此我可以看到列表在很大程度上是随机的。

但是在 Firefox 和 IE 中,排序并没有很好地发生。我看到第一个列表项在 10 次尝试中有 7 次保持在第一位。我可以看到许多其他项目也是如此。例如:项目 #5 在 10 次尝试中有 5 次出现在第三位。通过这些观察,我可以判断 JS 代码在 IE 和 Firefox 中无法正常工作。 (可能是由于引擎的差异导致不同浏览器对待JS代码的方式不同)

现在,我可以更改 JS 代码以使其在所有浏览器中都能正常工作吗?

或者有没有其他更好的排序算法,在使用 JS 实现时可以在所有浏览器中进行良好的排序?

我知道我的第二个问题的一部分已经在 SE 的其他问题中得到了回答,但我在这些问题中找不到关于“浏览器兼容性”的部分。

感谢您的帮助。

最佳答案

你的随机化不是很好:

// Get a random number between 0 and 10
var temp = parseInt( Math.random()*10 );
// Get 1 or 0, whether temp is odd or even
var isOddOrEven = temp%2;
// Get +1 or -1, whether temp greater or smaller than 5
var isPosOrNeg = temp>5 ? 1 : -1;
// Return -1, 0, or +1
return( isOddOrEven*isPosOrNeg );

这意味着在一半的情况下您会返回 0 ,它告诉排序函数这两个项目是相等的。一个好的排序函数会注意到这一点并且不会再询问。只有少数项目,您很有可能无法很好地分类这些项目。您可以通过计算(记录)您的比较函数被调用的频率来证明这一点。

此外,您不需要只返回 +1 , 0-1 ,您可以只返回任何正数或负数(另见下文)。对于随机化,您永远不需要返回相等性。所以,改用这个:

….sort( function() {
     return 0.5 - Math.random(); // that would be enough!
} );

但是,不应该使用 sort完全随机化。 Math.random不会导致总排序,排序不是为此而做的:(来自 EcmaScript specification )

If comparefn is […] not a consistent comparison function for the elements of this array, the behaviour of sort is implementation-defined.

A function comparefn is a consistent comparison function for a set of values S if all of the requirements below are met for all values a, b, and c (possibly the same value) in the set S: The notation a <CF b means comparefn(a,b) < 0; a =CF b means comparefn(a,b) = 0 (of either sign); and a >CF b means comparefn(a,b) > 0.

Calling comparefn(a,b) always returns the same value v when given a specific pair of values a and b as its two arguments. Furthermore, Type(v) is Number, and v is not NaN. Note that this implies that exactly one of a <CF b, a =CF b, and a >CF b will be true for a given pair of a and b.

  • Calling comparefn(a,b) does not modify the this object.
  • a =CF a (reflexivity)
  • If a =CF b, then b =CF a (symmetry)
  • If a =CF b and b =CF c, then a =CF c (transitivity of =CF)
  • If a <CF b and b <CF c, then a <CF c (transitivity of <CF)
  • If a >CF b and b >CF c, then a >CF c (transitivity of >CF)

NOTE: The above conditions are necessary and sufficient to ensure that comparefn divides the set S into equivalence classes and that these equivalence classes are totally ordered.

如果不满足这些属性,优化的排序函数很容易搞砸。这可能意味着根本没有排序以及永远不会终止排序。参见 Is it correct to use JavaScript Array.sort() method for shuffling?

相反,使用标准的洗牌算法,有很多好的算法。例如,Fisher-Yates-Shuffle 实现起来非常简单,参见问题 How to randomize (shuffle) a JavaScript array? .

关于javascript - 使用我用于随机化列表的 Javascript 代码的不同浏览器之间的结果不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13985083/

相关文章:

javascript - 隐藏用户事件的特定 Div(即点击)

python - 对 Pandas Series 的数据进行排序,然后按字母顺序优雅地按索引排序

javascript - jQuery 2.1.0 |增量显示元素

html - 在IE、Chrome、Firefox中定位不同

html - 如何在 HTML 中嵌入 Windows Media Player (WMV) 电影?

javascript - 如何使用纯 javascript 检测全屏 api 支持?

javascript - 正则表达式不匹配 6 个重复的数字

Javascript:多次触发鼠标悬停和鼠标移出的警报检查

javascript - 检查电话号码是否可用

Java - Arrays.sort 返回 0