在 Ruby 中,惯用地和干净地改进了 split 和 map 的使用,将字符串输入转换为 2d int 数组(即矩阵)
In Ruby, Idiomatically and cleanly improve on this use of split and map to turn string input to a 2d int array (i.e. a matrix)
我怀疑有比我所做的更简洁、更惯用的 Ruby 方式来解决这个难题。不过,我对 Ruby 太陌生了,无法确认。我的所有搜索都没有解决如何在下面给出的示例中最好地编写 Ruby 的问题。
问题是我需要输入字符串并将其转换为矩阵。行由 '\n'
分隔,行元素由 ' '
分隔
例如字符串输入 "2 6 4\n7 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 4\n7 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 为 "clean readability" 内置了很多方便的插件,例如
each_line
和 split
的默认参数
- 带有
.to_proc
快捷方式的符号,&
input = "2 6 4\n7 9 8"
input.each_line.map { |line| line.split.map(&:to_i) }
str = "2 6 4\n7 9 8\n"
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]]
我怀疑有比我所做的更简洁、更惯用的 Ruby 方式来解决这个难题。不过,我对 Ruby 太陌生了,无法确认。我的所有搜索都没有解决如何在下面给出的示例中最好地编写 Ruby 的问题。
问题是我需要输入字符串并将其转换为矩阵。行由 '\n'
分隔,行元素由 ' '
例如字符串输入 "2 6 4\n7 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 4\n7 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 为 "clean readability" 内置了很多方便的插件,例如
each_line
和split
的默认参数
- 带有
.to_proc
快捷方式的符号,&
input = "2 6 4\n7 9 8"
input.each_line.map { |line| line.split.map(&:to_i) }
str = "2 6 4\n7 9 8\n"
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]]