我从网站上获得了这段代码,用于随机化项目列表。 [这是一个音乐播放器,它在用户每次新访问时随机播放歌曲(列表),这样他们就不会因为从他们在过去访问时听到的同一首歌曲开始而感到无聊]
$(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 valuesS
if all of the requirements below are met for all valuesa
,b
, andc
(possibly the same value) in the setS
: The notationa <CF b
meanscomparefn(a,b) < 0
;a =CF b
meanscomparefn(a,b) = 0
(of either sign); anda >CF b
meanscomparefn(a,b) > 0
.Calling
comparefn(a,b)
always returns the same valuev
when given a specific pair of valuesa
andb
as its two arguments. Furthermore,Type(v)
is Number, andv
is notNaN
. Note that this implies that exactly one ofa <CF b
,a =CF b
, anda >CF b
will be true for a given pair ofa
andb
.
- Calling
comparefn(a,b)
does not modify the this object.a =CF a
(reflexivity)- If
a =CF b
, thenb =CF a
(symmetry)- If
a =CF b
andb =CF c
, thena =CF c
(transitivity of=CF
)- If
a <CF b
andb <CF c
, thena <CF c
(transitivity of<CF
)- If
a >CF b
andb >CF c
, thena >CF c
(transitivity of>CF
)NOTE: The above conditions are necessary and sufficient to ensure that
comparefn
divides the setS
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/