
Ruby Building Blocks 深度指南掌握 The Odin Project 课程中的变量、数据类型、字符串、数组与哈希【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum本篇文章以 The Odin Project 开放课程当前仓库 curriculum中 Ruby 基础阶段的 Building Blocks 章节为骨架系统梳理 Ruby 最核心的语法构件数字与运算符、字符串、数组、哈希、日期时间以及nil、puts/print/p、复合赋值等常用知识点。文章结合仓库内 ruby/basic_ruby/ 目录下的完整课程文档basic_data_types.md、arrays.md、hashes.md、input_and_output.md、variables.md对每个主题做深入展开。读完本文你将能够独立回答原文档 Learning Outcomes 中的全部自测问题并具备动手编写、运行基础 Ruby 脚本的实战能力。适用前提本文所有示例基于 Ruby 语言通用语义编写可配合 irb 或脚本文件运行验证。若尚未安装 Ruby可参考仓库中的 安装指南 完成环境准备。一、引言这一节在课程中的定位原文档lesson_building_blocks.md明确指出在 Foundations 阶段你已接触过 Ruby Basics对应仓库中的 ruby_basics_lesson.md而本节将在此基础上加深对变量、数据类型、字符串和方法的理解。它的覆盖面是整个 Ruby 课程中最广的——从最基础的算术运算到数组、哈希、日期时间再到nil、输出方法、复合赋值等杂项知识。建议的学习路线是先用 irb 逐条验证本文示例再回到文档的 Learning Outcomes 列表做自我测验最后完成 project_building_blocks.md 中的实战项目Caesar Cipher 与 Stock Picker来巩固。运行 Ruby 代码的三种方式IRB在命令行输入irb进入交互式环境逐行执行并立即看到返回值脚本文件将代码写入your_file.rb用$ ruby ./your_file_name_in_the_current_directory.rb运行在线编辑器使用支持 Ruby 的在线 REPL 平台。二、数字、运算符与表达式2.1 Integer 与 Float 的区别Ruby 有两种主要的数字类型Integer整数不带小数点的完整数字如10Float浮点数含小数点的数字如10.5、10.0、0.25。两者最重要的行为差异是整数除法当两个整数相除时结果永远是整数小数部分被直接截断而不是四舍五入17 / 5 # 3而不是 3.4要让除法结果精确只需把表达式中任意一个整数换成浮点数17 / 5.0 # 3.42.2 算术运算符一览Ruby 提供完整的数学运算符示例出自 basic_data_types.md1 1 # 2 加法 2 - 1 # 1 减法 2 * 2 # 4 乘法 10 / 5 # 2 除法 2 ** 2 # 4 指数注意 Ruby 用 ** 而不是 ^ 3 ** 4 # 81 8 % 2 # 0 取模求余数 10 % 4 # 22.3 整数与浮点之间的转换to_f和to_i用于类型互转。特别注意浮点转整数时直接截断小数位不做四舍五入13.to_f # 13.0 13.0.to_i # 13 13.9.to_i # 13 小数位被砍掉这也是原文档提醒转换时务必小心的原因精度丢失可能造成逻辑错误。2.4 常用数字方法6.even? # true 是否偶数 7.even? # false 6.odd? # false 是否奇数 7.odd? # true2.5、与是赋值运算符把右侧的值绑定给左侧变量是相等比较运算符判断两个值是否相等是case 相等运算符主要用于case/when语句和 Range、Regexp、Class 等对象上的模式匹配判断。对普通对象而言其默认行为等价于。2.6 Range范围Range 用于表示一段连续的值区间(1..3)包含终点等价于1, 2, 3(1...3)不包含终点等价于1, 2。创建 Range 的常用方式包括字面量(1..10)、Range.new(1, 10)、通过begin/end访问属性以及与字符串、字母等结合使用如(a..e)。三、字符串Strings3.1 单引号与双引号的区别字符串可以用单引号或双引号创建。两者最关键的差异是字符串插值interpolation和转义字符escape characters只在双引号内生效。3.2 字符串插值插值允许把变量或表达式直接嵌入字符串必须使用双引号name Odin puts Hello, #{name} # Hello, Odin puts Hello, #{name} # Hello, #{name} 单引号内原样输出3.3 转义字符与换行转义字符以反斜杠开头用于在字符串内表示空白字符或引号同样只在双引号内生效。原文档特别提醒实际开发中你最常遇到的只有\n换行和\t制表符但完整的常用列表如下\\ # 反斜杠 \b # 退格 \r # 回车 \n # 换行最常用 \s # 空格 \t # 制表符 \ # 双引号 \ # 单引号示例可在 irb 中验证irb(main):001:0 puts Hello \n\nHello Hello Hello nil3.4 字符串拼接的多种方式# 加号运算符 Welcome to Odin! # Welcome to Odin! # 铲子运算符shovel operator Welcome to Odin! # Welcome to Odin! # concat 方法 Welcome .concat(to ).concat(Odin!) # Welcome to Odin!3.5 访问特定字符与子串字符串可以像数组一样按下标访问Ruby 的 String 实现了切片语义hello[0] # h hello[0..1] # he hello[0, 4] # hell hello[-1] # o 负索引从末尾开始3.6 拆分字符串为数组hello world.split # [hello, world] hello.split() # [h, e, l, l, o]这与数组的join方法互为逆操作见下文数组部分体现了字符串与数组的相似性。3.7 其他常用字符串方法hello.capitalize # Hello hello.include?(lo) # true hello.upcase # HELLO Hello.downcase # hello hello.empty? # false .empty? # true hello.length # 5 hello.reverse # olleh hello, world .strip # hello, world # 替换与增删 he77o.sub(7, l) # hel7o 只替换第一个 he77o.gsub(7, l) # hello 全部替换 hello.insert(-1, dude) # hello dude hello world.delete(l) # heo word !.prepend(hello, , world) # hello, world!3.8 其他类型转字符串to_s方法几乎可以把任何对象转换成字符串5.to_s # 5 nil.to_s # :symbol.to_s # symbol3.9 字符串的可变性与用户输入清理字符串是**可变mutable**对象upcase!、gsub!等带!的方法会原地修改字符串本身。这意味着当你把字符串赋给多个变量时一个变量上的破坏性修改会影响所有指向同一内存地址的变量详见 variables.md 中的desired_location/johns_location示例。原文档提示对字符串字面量执行可变操作需谨慎Ruby 未来将限制此类操作。命令行获取用户输入使用gets它会返回输入内容含末尾换行符\n因此通常配合chomp清理new_string gets.chomp # 输入 This is a sentence. # This is a sentence. 已去掉换行3.10 Symbol符号与正则表达式Symbol是带冒号前缀的标识符如:my_symbol与字符串的关键区别在于内存存储方式字符串每次使用都会重新分配内存而 symbol 在整个程序中只存储一次因此更高效string.object_id string.object_id # false :symbol.object_id :symbol.object_id # true这一特性使 symbol 成为哈希键的首选见哈希章节。正则表达式RegEx用于模式匹配文本Ruby 中写作/pattern/字面量配合~、match、gsub等使用。原文档建议先完成基础的 Regex 教程再回来看 Ruby 具体语法。四、数组Arrays4.1 创建数组的多种方式# 数组字面量最常用 num_array [1, 2, 3, 4, 5] str_array [This, is, a, small, array] # Array.new 方法可预填充默认值 Array.new # [] Array.new(3) # [nil, nil, nil] Array.new(3, 7) # [7, 7, 7] Array.new(3, true) # [true, true, true]4.2 访问元素数组使用从 0 开始的索引也支持负索引从末尾倒数-1是最后一个元素str_array[0] # This str_array[-1] # array str_array[-2] # small str_array.first # This str_array.first(2) # [This, is] str_array.last(2) # [small, array]访问不存在的索引返回nil。4.3 修改、增删与组合数组在尾部增删push/ 铲子运算符追加pop弹出末尾num_array [1, 2] num_array.push(3, 4) # [1, 2, 3, 4] num_array 5 # [1, 2, 3, 4, 5] num_array.pop # 5在头部增删unshift在开头插入shift移除开头num_array [2, 3, 4] num_array.unshift(1) # [1, 2, 3, 4] num_array.shift # 1pop和shift还可接收数量参数批量移除[1,2,3,4,5,6].pop(3)返回[4,5,6]。组合数组或concat拼接保留重复元素-求差集移除第二数组中出现的所有元素a [1, 2, 3] b [3, 4, 5] a b # [1, 2, 3, 3, 4, 5] a.concat(b) # 同上 [1, 1, 1, 2, 2, 3, 4] - [1, 4] # [2, 2, 3]求交集用两数组共有的值并集用|。这是原文档中找出一个数组里有而另一个没有的值 / 找出两个数组都有的值的答案。删除元素delete、delete_at、delete_if等。原文档特别强调删除时要注意pop/shift返回被删除的元素而delete类的操作会改变索引遍历删除时易出错。4.4 常用查询与变换方法[].empty? # true [1, 2, 3].length # 3 [1, 2, 3].reverse # [3, 2, 1] [1, 2, 3].include?(3) # true [1, 2, 3].include?(3) # false严格类型比较 [1, 2, 3].join # 123 [1, 2, 3].join(-) # 1-2-3 [3, 1, 2].sort # [1, 2, 3] [1, 2, 2, 3].uniq # [1, 2, 3]去重 [3, 1, 2].max # 3 [3, 1, 2].min # 1数组转字符串用join其他类型转数组可用to_a、split字符串→数组、*展开运算符等。调用num_array.methods可列出数组的全部可用方法。4.5 命名约定与存储建议数组变量使用snake_case命名数组内建议存放同一类型的数据保持一致性以便后续遍历和处理。数组中可混合任意 Ruby 对象包括其他数组但混合类型会让代码难以维护。五、哈希Hashes5.1 什么是哈希哈希是数组的超强亲戚原文档原话通过键key→ 值value的映射存储数据相当于 JavaScript 的对象或 Python 的字典。与数组必须用数字索引访问不同哈希用有意义的名称键访问数据且键无序也能准确取到值。5.2 创建哈希的三种方式# 方式一哈希字面量hash rocket 语法 my_hash { a random word ahoy, Dorothys math test score 94, an array [1, 2, 3], an empty hash within a hash {} } # 方式二Hash.new my_hash Hash.new # {} # 方式三symbol 键的简洁语法见 5.5 japanese_cars { honda: Accord, toyota: Corolla }Hash rocket是运算符用于把键和值关联起来。哈希的值可以是数字、字符串、数组甚至是另一个哈希。5.3 访问与修改数据shoes { summer sandals, winter boots } shoes[summer] # sandals shoes[hiking] # nil键不存在返回 nil shoes.fetch(hiking) # 抛出 KeyError shoes.fetch(hiking, hiking boots) # hiking boots指定默认值 # 新增或修改键值对 shoes[fall] sneakers shoes[summer] flip-flops # 覆盖已有值5.4 删除、合并与枚举shoes.delete(summer) # 返回被删除的值 flip-flops # 合并两个哈希参数哈希的相同键覆盖接收者 hash1 { a 100, b 200 } hash2 { b 254, c 300 } hash1.merge(hash2) # { a 100, b 254, c 300 } # 列出全部键或值返回数组 books { Infinite Jest David Foster Wallace, Into the Wild Jon Krakauer } books.keys # [Infinite Jest, Into the Wild] books.values # [David Foster Wallace, Jon Krakauer]判断是否包含某键或值hash.key?(:key)/hash.has_key?(:key)、hash.value?(value)。哈希和数组都基于 Ruby 的Enumerable模块因此共享大量迭代方法each、map、select等这在后续的 lesson_advanced_building_blocks.md 中会详细展开。5.5 Symbol 键、Options 哈希与 Set用 symbol 作键在真实项目中占绝对多数因为 symbol 更高效且语法更简洁# Rocket 语法旧式 american_cars { :chevrolet Corvette, :ford Mustang } # Symbols 语法新式仅适用于 symbol 键 japanese_cars { honda: Accord, toyota: Corolla } # 访问时无论哪种创建方式都用标准 symbol 语法 american_cars[:ford] # Mustang japanese_cars[:honda] # Accord注意新式语法不能用于非 symbol 键如{ 9: value }会报语法错误。Options 哈希是把多个可选参数打包成一个哈希传给方法的惯用模式例如method_name(key: value1, option: value2)Ruby 会将其收集为方法内的最后一个哈希参数。Set是不重复元素的集合数据结构可通过require set引入适用于需要去重和高效成员判断的场景。六、日期与时间Dates and TimesRuby 提供Time和Date类处理时间# 当前日期和时间 Time.now # 提取各部分 t Time.now t.year # 2026 t.month # 9 t.hour # 5 t.sec # 34 t.wday # 1 星期几0 为周日 # 创建指定时刻2013 年 12 月 25 日 Time.new(2013, 12, 25) # 计算两个时刻之间的天数 (t2 - t1) / 86400 # 秒数差除以一天的秒数 # 相对时间100 秒前、10 天前 Time.now - 100 Time.now - 10 * 86400关于时区UTC协调世界时与GMT格林尼治标准时间在大多数实际场景中等价而Local是本机时区的时间。原文档强调不需要死记硬背全部 Time 格式化指令formatting directives只需知道它们存在、知道去哪里查即可。七、其他零散但高频的知识点7.1nil、blank与emptynil表示什么都没有是所有无返回值代码的默认返回值判断是否为nil用nil?empty?是对象方法字符串、数组、哈希都有判断是否为空容器blank?是 Rails 扩展ActiveSupport 提供比empty?更宽松空白字符串也算 blank。自测题中几个值属于nil还是empty # 非 nil非 empty含空格但 Rails 中是 blank # 非 nilempty [] # 非 nilempty [] # 非 nil非 empty含一个空字符串元素 {} # 非 nilempty7.2puts、print与p三者都是输出方法区别在于详见 input_and_output.mdprint输出后不换行返回nilputs输出后追加换行返回nilp输出对象的原始表示等价于调用inspect后再打印字符串会带引号便于调试。inspect方法返回对象的可读字符串表示p x本质上就是puts x.inspect。7.3 复合赋值运算符与并行赋值age 18 age 4 # 22 等价于 age age 4 age - 2 # 16 cash * 2 # 20 temperature / 10 # 4并行赋值允许一行内同时给多个变量赋值交换两个变量因此变得极简单a, b 1, 2 a, b b, a # a 2, b 1最简洁的交换方式7.4 变量命名约定Ruby 变量使用snake_case全小写、下划线分词名称应尽量清晰地描述所存内容这是写出可维护代码的基础习惯详见 variables.md# bad a 19 string John # good age 18 name John can_swim false八、实战验证Building Blocks 项目练习原文档配套的 project_building_blocks.md 包含两个经典入门问题用于检验上述知识点Project 1Caesar Cipher凯撒密码实现caesar_cipher(string, shift_factor)把字符串中每个字母替换为字母表上向后移动固定位数后的字母需处理z到a的回绕并保持大小写。 caesar_cipher(What a string!, 5) Bmfy f xywnsl!该题要求你把字符串与数字互相转换ord/chr、用范围判断字母、处理回绕与大小写——正好覆盖本课数字、字符串、范围三大主题。Project 2Stock Picker选股实现stock_picker(prices)给定每日股价数组返回最佳买入日和卖出日数组下标对要求买入先于卖出。 stock_picker([17,3,6,9,15,8,6,1,10]) [1,4] # 第1天买、第4天卖利润 $15 - $3 $12该题考验数组索引、循环与边界情况如最低价出现在最后一天、最高价出现在第一天的处理。仓库 ruby/basic_ruby_projects/ 目录下还有更多同类练习project_caesar_cipher.md、project_stock_picker.md可供继续巩固。九、自我测验与延伸学习路径完成本文阅读后回到 lesson_building_blocks.md 的Learning Outcomes部分逐条自测这是原文档明确要求的收尾动作。如果你能不看资料回答大部分问题就可以进入下一课 lesson_advanced_building_blocks.md那里会覆盖控制流、循环、块block、飞船运算符、Enumerable 模块each/map/select/inject等进阶主题。需要更深入的材料时仓库中还保留了 Ruby 课程的完整现代版本ruby/basic_ruby/ 下的 basic_data_types.md、arrays.md、hashes.md、variables.md、input_and_output.md 都是官方同步维护的深化文档配对的练习项目见 ruby/basic_ruby_projects/。提示本文所有示例均可直接在 irb 中运行验证写脚本时用$ ruby ./your_file.rb执行。多动手、多实验是消化这批最宽泛知识点的最佳方式。【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考