Ruby中map方法结合(&:first)的工作原理及代码解析
拆解Ruby代码:
remove_every_other的逻辑与&:first语法糖 让我一步步帮你理清这段代码的逻辑,尤其是你好奇的(&:first)部分——这是Ruby里非常实用的语法糖,搞懂它能让你写出更简洁优雅的Ruby代码~
先看整体功能
你的方法remove_every_other(arr)核心作用是:接收一个数组,移除每隔一个元素(也就是保留原数组中第1、3、5...个位置的元素,按0索引算就是0、2、4...位)。
逐行拆解代码
def remove_every_other(arr) arr.each_slice(2).map(&:first) end
第一步:arr.each_slice(2)
each_slice(n)是Ruby数组的内置方法,它会把原数组切割成多个长度为n的连续子数组。如果原数组长度不是n的整数倍,最后一个子数组会包含剩下的元素:
- 输入
['Hello', 'Goodbye', 'Hello Again'],会被切成:[['Hello', 'Goodbye'], ['Hello Again']] - 输入
[1,2,3,4,5,6,7,8,9,10],会被切成:[[1,2], [3,4], [5,6], [7,8], [9,10]] - 输入空数组
[],结果还是空数组
第二步:.map(&:first)
这部分是重点,我们分两部分理解:
1. map方法的作用
map会遍历前面each_slice(2)返回的每个子数组,对每个子数组执行指定操作,最后把所有操作结果收集成一个新数组返回。
2. &:first是什么?
这是Ruby的语法糖,完全等价于写:
map { |slice| slice.first }
具体拆解:
:first是一个符号(Symbol),它代表要调用的方法名first(数组的first方法会返回数组的第一个元素)&操作符的作用是:把后面的符号转换成一个Proc(Ruby里的匿名函数)。Ruby会自动调用Symbol#to_proc方法,把:first转成一个Proc,这个Proc的逻辑就是「接收一个对象,调用它的first方法」- 当
map遍历每个子数组时,会把子数组作为参数传给这个Proc,也就是执行slice.first,取每个子数组的第一个元素
结合测试用例验证
拿第一个测试用例来看:
Test.assert_equals(remove_every_other(['Hello', 'Goodbye', 'Hello Again']), #=> ['Hello', 'Hello Again'])
each_slice(2)把原数组切成[['Hello', 'Goodbye'], ['Hello Again']]map(&:first)分别对两个子数组调用first:- 第一个子数组
['Hello', 'Goodbye']的first是'Hello' - 第二个子数组
['Hello Again']的first是'Hello Again'
- 第一个子数组
- 最终返回的数组就是
['Hello', 'Hello Again'],和预期一致
再看单元素数组测试用例[[1,2]]:
each_slice(2)得到[[[1,2]]]map(&:first)取子数组的第一个元素,也就是[[1,2]],符合预期
总结
arr.each_slice(2).map(&:first)的逻辑就是:把原数组按每2个元素一组切割,然后取每组的第一个元素,这样就自然实现了「移除每隔一个元素」的需求。而&:first只是map { |x| x.first }的简洁写法,是Ruby为了让代码更优雅提供的语法糖。
内容的提问来源于stack exchange,提问作者KobbyAdarkwa
相关产品推荐
相关产品推荐

