最近,当我使用 JavaScript“sort()”函数时,我发现在一个 tutorials 中该函数不能正确排序数字。为了对数字进行排序,必须添加一个比较数字的函数,如以下代码:-
<script type="text/javascript">
function sortNumber(a,b)
{
return a - b;
}
var n = ["10", "5", "40", "25", "100", "1"];
document.write(n.sort(sortNumber));
</script>
然后输出如下:-
1,5,10,25,40,100
现在我不明白的是,为什么会发生这种情况,谁能详细说明这个“sort()”函数中使用的是什么类型的算法?这是因为对于任何其他语言,我都没有发现函数未正确排序数字 的问题。
非常感谢任何帮助。
最佳答案
为了回答您关于排序功能如何工作的问题,我将对其进行详细解释。正如这里的大多数答案所说,只调用 sort() on an array 将使用字符串对数组进行排序。也将整数转换为字符串。呸!
如果您将项目视为字符而不是数字,那么按这种方式排序是有道理的。了解这一点的一个好方法是为您的号码分配字母。
//0 = a
//1 = b
//2 = c
//4 = e
//5 = f
//These two arrays are treated the same because they're composed of strings.
var nums = ["10", "5", "40", "25", "100", "1"];
var chars = ["ba", "f", "ea", "cf", "baa", "b"];
//Here we can see that sort() correctly sorted these strings. Looking at the
//alphabetical characters we see that they are in the correct order. Looking
//at our numbers in the same light, it makes sense that they are sorted
//this way as well. After all, we did pass them as strings to our array.
chars.sort(); //["b", "ba", "baa", "cf", "ea", "f"]
nums.sort(); //["1", "10", "100", "25", "40", "5"]
//The bad part of sort() comes in when our array is actually made up of numbers.
var nums = [10, 5, 40, 25, 100, 1];
nums.sort(); //[1, 10, 100, 25, 40, 5]
//As a result of the default sorting function converting numbers to strings
//before sorting, we get an unwanted result. We can fix this by passing in our
//own function as a parameter to sort().
您可以通过将自己的函数作为参数传递给 sort() 来控制如何对数组进行排序。功能。这很好,但除非你知道 sort()功能有效,它真的不会对你有任何好处。
sort()将多次调用您的函数以重新排列数组。根据函数返回的内容告诉 sort()如何处理数组中的项目。如果返回负数或 0,则不会发生重新排列。如果返回正数,则这两项交换位置。 sort()跟踪它已经测试过的数字,因此它不会在切换项目后再次结束测试数字。如果sort()重新排列项目,它会向后移动一个位置,看看它之前是否测试过这两个项目。如果没有,它将测试它们。如果有,它将继续运行而不在它们上运行您的函数。
让我们举一个简单的例子,我将引导您完成它:
var arr = [50, 90, 1, 10, 2];
arr = arr.sort(function(current, next){
//My comments get generated from here
return current - next;
});
//1 : current = 50, next = 90
// : current - next (50 - 90 = -40)
// : Negative number means no re-arranging
// : Array now looks like [50, 90, 1, 10, 2]
//
//2 : current = 90, next = 1
// : current - next (90 - 1 = 89)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [50, 1, 90, 10, 2]
//
//If sort() didn't backtrack, the next check would be 90 and 10, switch those
//positions, check 90 and 2, and switch again. Making the final array
//[50, 1, 10, 2, 90], not sorted. But lucky for us, sort() does backtrack.
//
//3 : current = 50, next = 1
// : current - next (50 - 1 = 49)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 50, 90, 10, 2]
//
//If sort() wasn't smart, it would now check 50 and 90 again. What a waste!
//But lucky for us again, sort() is smart and knows it already made this
//check and will continue on.
//
//4 : current = 90, next = 10
// : current - next (90 - 10 = 80)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 50, 10, 90, 2]
//
//sort() backtracks one position and sees that it has not checked 50 and 10
//
//5 : current = 50, next = 10
// : current - next (50 - 10 = 40)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 10, 50, 90, 2]
//
//sort() backtracks one position and sees that it has not checked 1 and 10
//
//6 : current = 1, next = 10
// : current - next (1 - 10 = -9)
// : Negative number means no re-arranging
// : Array now looks like [1, 10, 50, 90, 2]
//
//sort() remembers that it already checked 10 and 50 so it skips ahead
//sort() remembers that it already checked 50 and 90 so it skips ahead
//
//7 : current = 90, next = 2
// : current - next (90 - 2 = 88)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 10, 50, 2, 90]
//
//sort() backtracks one position and sees that it has not checked 50 and 2
//
//8 : current = 50, next = 2
// : current - next (50 - 2 = 48)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 10, 2, 50, 90]
//
//sort() backtracks one position and sees that it has not checked 10 and 2
//
//9 : current = 10, next = 2
// : current - next (10 - 2 = 8)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [1, 2, 10, 50, 90]
//
//sort() backtracks one position and sees that it has not checked 1 and 2
//
//10: current = 1, next = 2
// : current - next (1 - 2 = -1)
// : Negative number means no re-arranging
// : Array now looks like [1, 2, 10, 50, 90]
//
//sort() remembers that it already checked 2 and 10 so it skips ahead
//sort() remembers that it already checked 10 and 50 so it skips ahead
//sort() remembers that it already checked 50 and 90 so it skips ahead
//sort() has no more items to check so it returns the final array
//which is [1, 2, 10, 50, 90]
如果您希望数组按降序排列 [90, 50, 10, 2, 1]您只需更改 return current - next; 的返回语句即可至 return next - current;像这样:
var arr = [50, 90, 1, 10, 2];
arr = arr.sort(function(current, next){
//My comments get generated from here
return next - current;
});
//1 : current = 50, next = 90
// : next - current (90 - 50 = 40)
// : Positive number means sort() will switch these positions in the array
// : Array now looks like [90, 50, 1, 10, 2]
//
//2 : current = 50, next = 1
// : next - current (1 - 50 = -49)
// : Negative number means no re-arranging
// : Array now looks like [90, 50, 1, 10, 2]
//
//etc.
不管你的数组是否由“字符串数字”组成"5"或者只是数字 5使用您自己的函数对数字进行排序时。因为当 JavaScript 在做数学运算时,它把“字符串数字”当作数字来对待。即 "5" - "3" = 2
当您对字符串进行排序时,您可以使用 > 来比较它们和 < (大于和小于)运算符。大于运算符按升序 (A-Z, 1-9) 对字符串进行排序,小于运算符按降序 (Z-A, 9-1) 对字符串进行排序。不同的浏览器使用不同的排序算法,因此在按字符串排序时,您必须确保返回 1 或 -1,而不是 true 或 false。
例如,这适用于 Chrome 和 FF,但不适用于 IE:
var arr = ['banana', 'orange', 'apple', 'grape'];
arr = arr.sort(function(current, next){
return current > next;
});
要确保您的排序算法在所有浏览器中都能正常工作,请使用三元运算符。
var arr = ['banana', 'orange', 'apple', 'grape'];
arr = arr.sort(function(current, next){
return current > next? 1: -1;
});
当更改排序方式(按升序或降序)时,除了更改运算符之外,您还可以保留相同的运算符并切换 current和 next变量,就像我们在排序数字时所做的那样。或者由于我们使用的是三元运算符,您可以切换 1和 -1 .
这里有一个巧妙的技巧,我想我会在这里添加。如果将对象添加到数组并使用它们的键进行比较,则可以对对象进行排序。这是一个例子。
var arr = [
{id: 2, name: 'Paul'},
{id: 1, name: 'Pete'}
];
//sort numerically
arr = arr.sort(function(current, next){
return current.id - next.id;
});
//Array now looks like [{id: 1, name: 'Pete'}, {id: 2, name: 'Paul'}]
//sort alphabetically
arr = arr.sort(function(current, next){
return current.name > next.name? 1: -1;
});
//Array now looks like [{id: 2, name: 'Paul'}, {id: 1, name: 'Pete'}]
对数字进行排序
按升序(1、2、3...):function(a, b){return a - b;}
按降序排列(9、8、7...):function(a, b){return b - a;}
对字符串进行排序
按升序(A、B、C...):function(a, b){return a > b? 1: -1;}
按降序(Z、Y、X...):function(a, b){return b > a? 1: -1;}
要对对象进行排序,请将它们添加到数组中,
然后按键排序:function(a, b){return a.key - b.key;}
关于javascript - JavaScript "sort()"函数的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3423394/
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub