ruby 的 <=> 运算符和排序方法

2023-11-21

player1 = Player.new("moe")
player2 = Player.new("larry",60)
player3 = Player.new("curly", 125)
@players = [player1, player2, player3]

上面,我创建了一些玩家对象并将它们添加到之前的空数组 @players 中。

然后,我将 重新定义为:

def <=>(other)
    other.score <=> score
end 

然后我可以运行这段代码

@players.sort

我在 @players 中的玩家对象数组按从高分到低分的顺序排序。 我想这对我来说看起来有点黑四四方方。我有点不清楚这里发生了什么。我如何了解幕后发生的事情?

我所知道的是,如果你取两个值并使用宇宙飞船运算符/通用比较运算符:

2 <=> 1   
=> 1

1 <=> 2
=> -1

1 <=> 1
=>0

有时,Ruby 似乎有很多较低级别的内容,而我在编程的高级级别上看不到这些内容。这似乎很自然……但这种情况似乎特别远离了较低级别的内容排序方法。 sort如何使用太空船运算符?为什么以我们之前的方式重新定义飞船运算符可以让我们现在对对象进行排序?


在您能够理解对象排序之前。您需要了解 Ruby 中的 .sort 方法。如果您要对 5 张带有数字的卡片进行排序,您可以查看所有卡片,轻松找到最低的一张,然后选择那一张作为您的第一张卡片(假设您从最低到最高排序,Ruby做)。当你的大脑进行排序时,它可以查看所有内容并从那里进行排序。

这里有两个主要的混淆因素很少被解决:

1) Ruby 无法按照您想象的“排序”一词的方式进行排序。 Ruby 只能“交换”数组元素,也可以“比较”数组​​元素。

2) Ruby 使用称为 spaceship 的比较运算符来对数字进行属性以帮助其“排序”。这些数字是-1,0,1。人们错误地认为这 3 个数字正在帮助它“排序”(例如,如果有一个包含 3 个数字的数组,例如 10、20、30,那么 10 将是 -1,20 将是​​ 0,30 将是 1 ,而 Ruby 只是通过将其减少为 -1,0,1 来简化排序。这是错误的。Ruby 不能“排序”。它不能只进行比较)。

看看宇宙飞船的操作员。它由 3 个单独的运算符合为一个:。当 Ruby 比较两个变量时,它会得出这些数字之一。

Spaceship Operator

那么,“结果”是什么意思呢?这并不意味着其中一个变量被分配了 0,1,-1。这只是 Ruby 获取两个变量并用它们做某事的一种方式。现在,如果你运行:

puts 4 <=> 5

您将得到 -1 的结果,因为比较运算符(宇宙飞船)的任何“部分”(例如 )为 true,都会获取分配给它的数字(如上图所示) 。当 Ruby 看到这个 与数组时,它只会对数组做两件事:保留数组或交换数组的元素。

如果 Ruby 使用 并得到 1,它将交换数组的 2 个元素。如果 Ruby 得到的结果是 -1 或 0,它将不处理该数组。

一个例子是 Ruby 看到数组 [2,1]。 sort 方法将使其提取这些数字,如 21。由于宇宙飞船的部分(如果你想这样想的话)为真的是 > (即 2>1 为真),所以 Ruby 的结果是“1”。当 Ruby 从宇宙飞船中看到 1 结果时,它swaps数组的 2 个元素。现在数组是[1,2]。

希望此时您会看到 Ruby 仅与 运算符进行比较,然后交换(或保留)它比较的数组中的 2 个元素。

了解 .sort 方法是一种迭代方法,这意味着它是一种多次运行代码块的方法。大多数人只是在看到 .each 或 .upto 等方法之后才会了解 .sort 方法(如果您没有听说过它们,则无需知道它们的作用),但这些方法贯穿始终仅阵列 1 次。 .sort 方法的不同之处在于,它将根据需要多次运行数组,以便对其进行排序(通过排序,我们的意思是比较和交换)。

为了确保您理解 Ruby 语法:

foo = [4, 5, 6]
puts foo.sort {|a,b| a <=> b}

代码块(由 {} 包围)是 Ruby 从最低到最高排序时会执行的操作。但只要说 .sort 方法的第一次迭代将在管道 (a, b) 之间分配数组的前两个元素的变量就足够了。因此,对于第一次迭代 a=4 和 b=5,并且由于 4 结果均为 -1,Ruby 停止循环并感觉数组已按 [4,5,6] 排序。

我们可以通过简单地交换变量的顺序来从高到低排序。

bar = [5, 1, 9]
puts bar.sort {|a,b| b <=> a}   

这是 Ruby 正在做的事情:

迭代 1:数组 [5,1,9]。 a=5,b=1。 Ruby 看到 ba,并说 1

迭代 2:数组 [5,1,9]。 a=1,b=9。 Ruby 看到 ba,并说 9

迭代 3:数组 [5,9,1]。从 b/c 开始,在遍历所有内容之前,数组中有 +1 结果。 a=5,b=9。 Ruby 看到 ba,说是 9

迭代 4:数组 [9,5,1]。 a=5,b=1。 Ruby 看到 ba,说是 1

想象一个数组,前 999 个元素的编号为 50,第 1000 个元素的编号为 1。如果您意识到 Ruby 必须遍历该数组数千次,执行相同的简单比较和交换例程才能进行移位,那么您就完全理解了排序方法那1一直到数组的开头。

现在,我们终于可以看看对象的 .sort 了。

def <=>(other)
    other.score <=> score
end 

现在这应该更有意义了。当对对象调用 .sort 方法时,例如运行以下命令时:

@players.sort

它使用参数(例如“other”)提取“def ”方法,该参数具有来自@players的当前对象(例如“无论当前实例对象是什么”@players',因为它是排序方法,它最终会遍历“@players”数组的所有元素)。就像当您尝试在类上运行 put 方法时,它会自动调用该类内的 to_s 方法。 .sort 方法自动查找 方法也是如此。

查看 方法内部的代码,该类中必须有一个 .score 实例变量(带有访问器方法)或只是一个 .score 方法。 .score 方法的结果应该(希望)是一个字符串或数字——这是 ruby​​ 可以“排序”的两件事。如果它是一个数字,那么 Ruby 使用它的 'sort' 操作来重新排列所有这些对象,现在它知道要对这些对象的哪一部分进行排序(在本例中,它是 .score 方法或实例变量的结果) )。

最后一点,Ruby 还通过将其转换为数值来按字母顺序排序。它只考虑为任何字母分配 ASCII 代码(这意味着由于大写字母在 ASCII 代码表上的数值较低,因此默认情况下大写字母会排在第一位)。

希望这可以帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ruby 的 <=> 运算符和排序方法 的相关文章

  • 如何从 Rails 中的 date_select 或 select_date 获取日期?

    Using select date给我回一个params my date with year month and day属性 如何轻松获取 Date 对象 我希望有类似的事情params my date to date 我很高兴使用date
  • Ruby 中的任务/未来

    代表潜在延迟的异步计算并且可以订阅其完成的模式的惯用 Ruby 模拟是什么 即类似于 NET 的东西System Threading Task 或Python 3 xconcurrent futures future 请注意 这并不一定意味
  • 我在 Rails 中使用了保留字吗?

    这是我的模型 class Record lt ActiveRecord Base belongs to user belongs to directory end class Directory lt ActiveRecord Base h
  • Rails:named_scope、lambda 和块

    我认为以下两个是等效的 named scope admin lambda company id conditions gt company id company id named scope admin lambda do company
  • rvm gem 安装错误?

    我正在摆弄 ruby gems 和 rvm 它工作得很好 但现在当我尝试安装 gem 时出现错误 gem install Rails错误 同时 执行 gem Errno EACCES 权限被拒绝 Users da rvm gems ruby
  • 我无法让 ruby​​ 开发工具包适用于 Windows XP

    所以 我一生都无法让它正常工作 我的最终目标是安装 dbd odbc gem 并使其正常工作 从我读过的多篇文章来看 我需要安装ODBC 绑定 http www ch werner de rubyodbc 对于 ruby 以及 dbd od
  • ruby从1.8.7升级到1.9.2(使用Rails 3.1.1)后本地服务器错误

    我刚刚安装了rvm并使用rvm将ruby从1 8 7升级到1 9 2 我在我的应用程序上运行了捆绑安装 它重新安装了我的 gems 当我在本地运行 Rails 服务器并将浏览器导航到 localhost 3000 时 服务器日志中显示以下错
  • ruby 正则表达式匹配模式的多次出现

    我正在寻找构建一个 ruby 正则表达式来匹配模式的多次出现并将它们返回到数组中 模式很简单 即 两个左括号 一个或多个字符 后跟两个右括号 这就是我所做的 str Some random text lead first name and
  • 使用rSpec 测试delayed_job 链的最佳方法是什么?

    目前 当我的代码中有一个延迟方法时 如下所示 CommentMailer delay deliver comments comment true 我在规范中写了这样的内容 dj mock DelayProxy CommentMailer s
  • 使用哈希参数进行 DRY Ruby 初始化

    我发现自己经常在构造函数中使用哈希参数 尤其是在为配置或最终用户将接触到的其他 API 编写 DSL 时 我最终做的是类似以下的事情 class Example PROPERTIES name age PROPERTIES each p a
  • 在 Sinatra 中运行后台进程

    我有 Sinatra Rails 应用程序和一个启动一些漫长过程的操作 通常我会为后台作业排队 但这种情况太简单了 后台进程很少启动 所以队列是一个开销 那么如何在没有队列的情况下运行后台进程呢 get build logs project
  • Watir Webdriver 加载 Chrome 扩展

    我正在尝试使用 Watir 加载 chrome 扩展 但遇到了问题 我发现这个相关问题 能够启动带有 watir webdriver 加载扩展的 chrome https stackoverflow com questions 125867
  • 我可以让这个 Ruby 代码更快并且/或使用更少的内存吗?

    我有一个Array of StringRuby 中的对象由如下单词组成 animals cat horse dog cat dog bird dog sheep chicken cow 我想将其转换为另一个Array of String对象
  • 子文件夹和关系中的 Rails 模型

    我在自动加载的文件夹中组织了一些轨道模型 config autoload paths Dir Rails root join app models 我可以直接使用所有模型 例如Image first file name 但是当我尝试通过关系
  • 嵌套 has_one 关联的强参数

    我似乎遗漏了一些明显的东西 但我无法允许嵌套的属性has one协会 控制器 def create crossword Crossword new crossword params if crossword save render show
  • Ruby 动态变量名

    有没有办法在 Ruby 中创建具有动态名称的变量 我正在读取一个文件 当我找到一个字符串时 会生成一个哈希值 e g file File new games log r file lines do l l split do p if p 1
  • rake db 问题:迁移 -

    我无法为 Ruby on Rails 设置 MySQL 数据库 设置数据库并确保 config database yml 文件匹配后 我遇到了以下错误消息 U Rails alpha gt rake db migrate trace in
  • Ruby:如何在不创建新实例的情况下检查实例方法的参数?

    在 Ruby 1 9 2 中 您可以使用 method symbol 检查任何方法的参数 如何在不创建新车的情况下检查 Car initialize 方法 class Car def initialize fuel type passeng
  • 从 Ruby on Rails 应用程序运行 phantomjs

    我有兴趣使用幻影 http www phantomjs org 我想从我的 Ruby on Rails 应用程序运行它 然而 这是一个命令行工具 即我需要运行类似phantomjs rasterize js http raphaeljs c
  • ruby 字符串到哈希值的转换

    我有一个这样的字符串 str uu p xx m yy n zz m 我想知道如何将给定的字符串转换为哈希值 即我的实际要求是 有多少个值 符号之前 有m n和p 我不需要计数 我需要一个精确的值 这样输出效果会更好 m gt xx zz

随机推荐

  • 0x9d 在什么 8 位字符集中有意义?

    英语的 8 位类似 ASCII 的字符集是什么0x9d有意义吗 我正在清理一些旧的数据文件 偶尔会发现0x9d在其他 ASCII 文本中 不 这不是 UTF 8 它在 Windows 1252 中无效 Python latin 1 编解码器
  • 如何在 iPhone sdk 中创建 Excel 工作表和文件?

    我想生成应用程序来在 iPhone sdk 中创建 excel 文件 任何人都可以建议我创建它 嗯 对的人看到了你的帖子 SourceForge 上有一个开源 C 库 xlslib 这将完全满足您的需要 但是等等 还有更多 有一个 Obje
  • 限制访问 Web ASP .NET 应用程序的用户数量

    如何限制 Web 应用程序的用户数量 您可能希望将 Web 应用程序限制为一次仅处理 20 个用户 我们公司销售基于多个许可证的应用程序 但我们不确定网络应用程序中的行为是什么 我看到一些建议说 当用户登录时 您可以将用户帐户标记为 Log
  • android logcat中的致命信号6是什么[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我是 Android 开发新手 我的应用程序在从 Activity 切换 11 次时不断被终止 而且它只说 致命信号 6 SIGABRT tid 9485 中的代码 6 Thre
  • Python/SciPy:如何从 CubicSpline 获取三次样条方程

    我正在通过给定的一组数据点生成三次样条曲线图 import matplotlib pyplot as plt import numpy as np from scipy import interpolate x np array 1 2 4
  • 如何从 Tomcat Java 应用程序捕获 SOAP 消息到外部服务器?

    我有一个 Web 应用程序 它在 Tomcat6 内运行并通过 HTTPS 将 SOAP 消息发送到某个外部系统 我想拦截这些消息 为了做到这一点 我在工具 gt Fiddler 选项对话框 重新启动 Fiddler 后 我可以看到对多个主
  • 如何读取内存中存储的图像文件?

    在我的 Android 应用程序中 我使用以下代码将图像文件存储在内部存储器中 FileOutputStream fos con openFileOutput fileName con MODE PRIVATE fos write baf
  • 在不同的控制器中设计表单

    我正在使用 devise gem 进行登录 退出程序 我从设备生成视图文件 使用rails g devise views 我看到有一个 devise sessions new html erb 文件 其中包含登录表单 我创建了另一个文件 d
  • TypeScript - 检查对象的属性是否是具有给定签名的函数

    我有一个从对象获取属性的函数 Utils ts export function getProperty
  • 如何在 Java 中将电话号码格式化为字符串?

    我一直将电话号码存储为很长的长度 我想在将电话号码打印为字符串时简单地添加连字符 我尝试使用DecimalFormat但这不喜欢连字符 可能是因为它用于格式化十进制数字而不是长整数 long phoneFmt 123456789L Deci
  • Android studio java.exe 以非零退出值 3 结束

    我已经通过了与 multidex 问题相关的非零退出值 1 2 但现在我得到了非零退出值 3 工作室留言 Information Gradle Executing tasks emoticons lib proj assembleDebug
  • 通过AJAX调用提示用户保存文件

    我正在将 DHTMLX 网格导出到 csv 并已成功创建 CSV 文件 我遇到的问题是它没有提示用户保存 打开文件 我使用 javascript 中的 post 调用将 CSV 字符串发送到 PHP 然后将该字符串写入 csv 由于某种原因
  • 如何在 C# 中使用 imageMagick

    您能解释一下如何将 ImageMagick 与 C 一起使用吗 我正在尝试将 PDF 页面转换为图像 我想运行 imageMagick 命令 convert 密度 300 input pdf output png string argume
  • 获取类函数的参数数量

    有没有办法检测类中函数的参数数量 我想做的是以下内容 class foo path path to file if file exists path die require path if class exists class die c
  • 在 Maps V2 上绘制多色折线

    我按照以下方式在地图上绘制纯色折线 效果很好 PolylineOptions polyLine new PolylineOptions polyLine width 5 polyLine color Color RED polyLine g
  • WPF 的语法荧光笔[重复]

    这个问题在这里已经有答案了 我目前正在为 WPF 应用程序寻找语法荧光笔 用户可以在文本框中输入内容 希望能够识别代码并相应地突出显示语法 我想先支持C 稍后再支持其他语言 问题重复394751 如果您不介意没有任何文档 Avalon编辑是
  • 使用@EJB时,每个托管bean是否都有自己的@EJB实例?

    我正在将 JSF 2 2 用于 Web 项目 并且现在正在实现登录页面 我有一个login xhtml作为view 和一个名为的支持 beanUserLoginView 这种豆子有一个EJB属性beanprivate UserService
  • 组合类型别名的协议和空一致协议之间的区别

    Swift 中这两者有区别吗 protocol ABProtocol AProtocol BProtocol typealias ABProtocol AProtocol BProtocol 为了让事情更清楚 我将第二个重命名为 typea
  • 从变量中批量提取路径和文件名

    如何从变量中提取路径和文件名 Setlocal EnableDelayedExpansion set file C Users l72rugschiri Desktop fs cfg 我想在不使用任何函数或任何 GOTO 的情况下做到这一点
  • ruby 的 <=> 运算符和排序方法

    player1 Player new moe player2 Player new larry 60 player3 Player new curly 125 players player1 player2 player3 上面 我创建了一