我怀疑有一种比我做的更干净、更惯用的 Ruby 方法来解决这个难题。不过,我对 Ruby 来说太新了,无法确认。我所有的搜索都没有解决如何在下面给出的例子中最好地编写 Ruby 的问题。
难题是,我需要获取字符串输入并将其转换为矩阵。行用'n'
分隔,行元素用' '
例如,字符串输入"2 6 4n7 9 8"
具有输出[[2, 6, 4], [7, 9, 8]]
即矩阵:
2 6 4
7 9 8
这是我的解决方案:
@rows = in_string.split(/n/).map{|str| str.split(' ').map{|ch| ch.to_i}}
解释正在发生的事情
"2 6 4n7 9 8"
=> 按换行符拆分 =>["2 6 4", "7 9 8"]
- 映射从 1. 到拆分的元素
' '
=>[["2", "6", "4"], ["7", "9", "8"]]
- 映射 2. 的元素以变为
int
s(每行发生一次) - 鳍。我们有我们追求的结果
我觉得这段代码不是很好读,但我来自 rust,所以我不习惯好的风格
我对Ruby不够熟悉,无法理解编写此类解决方案的好方法。我试过使用更多这样的行
@rows = in_string.split(/n/).map{
|str| str.split(' ').map{
|ch| ch.to_i
}
}
但我仍然觉得不知道什么可以被认为是好的风格,或者还有什么其他选择。
代码的正确性很好。对我来说,一个很好的答案是让我了解将来在深入研究类似问题时要注意什么,并对我理解什么是优雅的 Ruby 代码更有信心。
从答案编辑到目前为止的建议
- 对拆分使用默认值
- 在地图上使用默认值
- 使用
do-end
(我还没有学会)。如果有人想编辑这个,太棒了。
这就是我最终得到的:@rows = in_string.split(/n/).map( |chrs| chrs.split.map( &:to_i ) )
你的代码对我来说看起来不错。
in_string.split(/n/).map { |row| row.split.map(&:to_i) }
我们通常只是避免使用{}
的多行块。对多行块使用do-end
。
我发现的两个小改进
split
默认参数为' '
- 如果你不需要块,就不要使用它。只需将过程传递给它
map(&:to_i)
我认为这已经足够好了。 如果您认为嵌套块不好阅读。 您可以定义一个方法,例如
def to_int_arr(str)
str.split(' ').map(&:to_i)
end
in_string.split(/n/).map{|str| to_int_arr(str)}
顺便说一句,最好在多行块中使用do end
Ruby内置了很多方便的"干净可读性",例如
each_line
和split
的默认参数- 带有
.to_proc
快捷方式的符号,&
input = "2 6 4n7 9 8"
input.each_line.map { |line| line.split.map(&:to_i) }
str = "2 6 4n7 9 8n"
arr = str.split.map(&:to_i)
#=> [2, 6, 4, 7, 9, 8]
arr.each_slice(arr.size/str.lines.size).to_a
#=> [[2, 6, 4], [7, 9, 8]]