如何在JavaScript中使用sortingfunction以及比较function
正如已经问到的那样:在JavaScript中如何使用sorting函数以及compare
函数? 如果我有一个数组,现在我做了array.sort(compare)
现在写在书中,如果compare
函数返回ab
(数组的两个索引),那么它的工作原理是,结果是否大于0,小于0或等于0.但是,它究竟是如何工作的呢? 我无法解决这个问题。
“比较”函数必须有两个参数,通常称为a和b 。 然后,根据这些值a和b ,使比较函数返回0,大于0或小于0。
- 如果a大于b,则返回大于0
- 如果a等于b,则返回0
- 如果a小于b,则返回小于0
有了这三个返回值,只有两个参数,可以编写一个比较函数,它可以对任何types的input数据types或复杂的数据结构进行sorting。
然后,当你调用sort()时,用你自定义的比较函数,比较函数将在你的待分类列表中的对上调用,以确定正确的sorting。
让我们通过一个简单的例子…假设你只是sorting一些数字,所以我们有一个非常简单的比较函数:
function compare(a,b) { return a - b; }
如果a大于b,简单地从a中减去b将总是返回大于零,如果它们相等,则返回0;如果a小于b,则返回小于零。 所以它符合比较function的要求。
现在让我们假设这是我们要sorting的数字列表:
var numbers = [1,5,3.14];
当你调用numbers.sort(compare)
,内部会实际执行:
compare(1,5); // Returns -4, a is less than b compare(1,3.14); // Return -2.14, a is less than b compare(5,3.14); // returns 1.86, a is greater than b
如果你曾经做过手工sorting或字母sorting,你完成了完全相同的事情,可能没有意识到。 即使你可能有几十或几百个项目要比较,你一直只比较两个数字(或作者的姓氏,或其他)。 再次浏览一下三个数字,你会开始比较前两个数字:
- 1大于还是小于5? 不到,所以把这两个数字放在我们的列表中:1,5
- 3.14大于还是小于1? 大于,所以它在新列表中的1之后
- 我们的新名单中3.14大于还是小于5? 不到,所以它在5之前。我们的新名单现在是[1,3.14,5]
因为您可以提供自己的compare()函数,所以可以对任意复杂的数据进行sorting,而不仅仅是数字。
默认情况下,数组sort()
方法按字母顺序升序sorting。 如果你想以其他顺序sorting,因为你的数组包含数字或对象,那么你可以将一个函数传递给sort()
。
传入的函数有两个参数,通常称为a和b,并返回:如果第一个参数应该在第二个参数之前sorting,则返回负数(a <b)如果参数相等则为0(a == b)为正如果第一个参数应该排在第二个之后(a> b)
现在, 这里是关键的一点 :作为sort()
parameter passing的函数在处理整个数组时会被sort()
重复调用。 sort()
不知道或关心数组中的事物的数据types:每次需要知道“项目A是否在项目B之前? 它只是调用你的function。 您不必担心sort()
内部使用什么types的sortingalgorithm,实际上一个浏览器可能使用另一个algorithm,但这没关系,因为您只需提供一种方法来比较任何两个项目从你的arrays。
你的函数可以有一个if / else if / else
结构来决定返回的结果,但是对于你简单地返回(ab)的数字,你会得到这个结果,因为减法的结果是-ve,0或者+ ve并且正确的数字按升序排列。 返回(ba)会使他们下降:
var sortedArray = myArray.sort(function(a,b){ return (ab); });
如果你有一个对象数组,并想对某些特定的属性或属性进行sorting,你也可以这样做。 假设,例如,这种格式的对象:
{ id : 1, name : "Fred", address : "12 Smith St", phone : "0262626262" }
然后你可以通过它们的'id'属性来sorting这些对象的数组,如下所示:
var sortedArray = myArray.sort(function(a,b){ return (a.id - b.id); });
或者,您可以按照如下所示按“name”属性(按字母顺序排列)对这些对象进行sorting:
var sortedArray = myArray.sort(function(a,b){ if (a.name < b.name) return -1; else if (a.name == b.name) return 0; else return 1; });
请注意,在我最后的例子中,我已经把前面提到的完整的if / else if / else
结构。
对于用多个属性sorting对象的示例,您可以进一步扩展以包含次要sorting,也就是(在我的示例中)如果名称属性相同,则可以返回比较(例如,电话属性)。
此方法使用Array.sort(compareFunction sortOptions)的顺序的语法和参数,其参数定义如下:
compareFunction – 用于确定数组元素sorting顺序的比较函数。 该参数是可选的。 比较函数应该用来比较这两个参数。 给定元素的A和B,compareFunction的结果可以为负值,即0或正值:
如果返回值是负值,则意味着A在sorting的序列中出现在B之前。 如果返回值为0,则A和B具有相同的sorting顺序。 如果返回值是正数,则意味着A在sorting后的序列中出现在B之后。
单独的sorting方法将数字视为string,所以如果string数组不需要比较函数。 但是如果数组数组需要使用比较函数来改变sorting方法的构build行为。
ex1:string
var animals = ["Horse", "Cat", "Tiger", "Lion"]; animals.sort();
例2:数字
var marks = [70, 90, 60, 80 ]; marks.sort(function(a, b){return a > b}); //ascending , a < b descending .
我想这可能是这样的(当然,我不确定)。
假设函数compare(a,b)
是比较函数。 它返回c
。 假设我们要对数组N
的条目进行sorting,以得到sorting结果数组M
我不知道确切的sortingalgorithm,如果c
既不是(ab)
也不是(ba)
(如果c
是"b-2"
, "a+b"
或其他expression式),那么不同的浏览器甚至返回不同的结果。 。
但根据ECMA-262
,sorting结果应该是这样的:
a,b可以是任何两个索引。 这意味着我们实际上将一个有序对传递给比较函数。 eg: (0,1),(1,4), or even (2,0) , (2,1)
。
ECMAScript语言规范说结果应该有这个属性: (a,b)
是一个传递给比较函数的有序对。
- 如果
c
(函数返回的)小于零,则必须满足M(a)< M(b)
。
并且规范没有说明如果c是零或大于零会发生什么。
我不确定这是否正确。 至less这可以很容易地解释为什么当c
是"ab"
,条目被sorting为数字和升序,为什么当c
是"ba"
,条目被sorting到相反。
浏览器的js引擎是不是严格按照ECMA-262devise的,还是我完全错了?
参考:
第五版ECMA-262(检查第129-130页)