在 Ruby 中的同一行中打印不同大小数组的数组元素
Print elements of array of arrays of different size in same line in Ruby
也许有人可以帮我解决这个问题。我有一个数组数组。内部数组有不同的大小(从 2 到 4 个元素)。
letters = [["A", "B"],["C", "D", "F", "G"],["H", "I", "J" ]]
我试图在同一行中打印每个数组的第一列元素[0]和元素[1]连接,第二列元素[0]、元素[1]、元素[2]连接作为第 3 列元素[0]、元素[1]、元素[3] 加入。元素 2 和 3 并不总是存在。
我试图得到的输出是这样的:
AB
CD CDF CDG
HI HIJ
我正在这样做,但我收到了这个错误。
letters.map{|x| puts x[0]+x[1] + "," + x[0]+x[1]+x[2] + "," + x[0]+x[1]+x[3]}
TypeError: no implicit conversion of nil into String
from (irb):1915:in "+"
from (irb):1915:in "block in irb_binding"
from (irb):1915:in "map"
from (irb):1915
from /usr/bin/irb:11:in "<main>"
看起来你想加入前两个字母,然后对剩余的字母进行笛卡尔积。
letters.each do |arr|
first = arr.take(2).join
rest = arr.drop(2)
puts [first, [first].product(rest).map(&:join)].join(" ")
end
这提供了您指定的准确输出。
letters.each do |a,b,*rest|
puts rest.each_with_object([a+b]) { |s,arr| arr << arr.first + s }.join(' ')
end
打印
AB
CD CDF CDG
HI HIJ
步骤如下
假设
letters = [["C", "D", "F", "G"],["H", "I", "J" ]]
然后
enum0 = letters.each
#=> #<Enumerator: [["C", "D", "F", "G"], ["H", "I", "J"]]:each>
生成此枚举器的第一个元素并传递给块,并为三个块变量赋值。
a, b, *rest = enum0.next
#=> ["C", "D", "F", "G"]
a
#=> "C"
b
#=> "D"
rest
#=> ["F", "G"]
接下来,我们得到
enum1 = rest.each_with_object([a+b])
#=> rest.each_with_object(["CD"])
#=> #<Enumerator: ["F", "G"]:each_with_object(["CD"])>
生成此枚举器的第一个元素并传递给块,块变量被赋值。
s, arr = enum1.next
#=> ["F", ["CD"]]
s
#=> "F"
arr
#=> ["CD"]
现在执行块计算。
arr << arr.first + s
#=> arr << "CD" + "F"
#=> ["CD", "CDF"]
生成 enum1
的第二个也是最后一个元素并传递给块,块变量被赋值并计算块。
s, arr = enum1.next
#=> ["G", ["CD", "CDF"]]
arr << arr.first + s
#=> ["CD", "CDF", "CDG"]
当尝试从 enum1
生成另一个元素时,我们获得
enum1.next
#StopIteration: iteration reached an end
Ruby 通过跳出块并返回 arr
来处理异常。然后加入 arr
的元素:
arr.join(' ')
#=> "CD CDF CDG"
并打印出来。
现在生成enum0
的第二个也是最后一个元素,传递给块,三个块变量赋值。
a, b, *rest = enum0.next
#=> ["H", "I", "J"]
a
#=> "H"
b
#=> "I"
rest
#=> ["J"]
其余计算类似。
有些读者可能不熟悉Enumerable#each_with_object这种被广泛使用的方法。阅读文档,但请注意,这里它产生的结果与如下代码编写的结果相同。
letters.each do |a,b,*rest|
arr = [a+b]
rest.each { |s| arr << arr.first + s }
puts arr.join(' ')
end
通过使用 each_with_object
,我们避免了对语句 arr = [a+b]
和语句 puts arr.join(' ')
的需要。这两个语句的功能当然在使用 each_with_object
的行中,但是大多数 Ruby 用户更喜欢当 chaining each_with_object
到join(' ')
。另一个区别是 arr
的值被限制在 each_with_object
的块中,这是一个很好的编程习惯。
出于好奇,Enumerable#map
-唯一的解决方案。
letters = [["A", "B"],["C", "D", "F", "G"],["H", "I", "J" ]]
letters.map do |f, s, *rest|
rest.unshift(nil).map { |l| [f, s, l].join }.join(' ')
end.each(&method(:puts))
#⇒ AB
# CD CDF CDG
# HI HIJ
也许有人可以帮我解决这个问题。我有一个数组数组。内部数组有不同的大小(从 2 到 4 个元素)。
letters = [["A", "B"],["C", "D", "F", "G"],["H", "I", "J" ]]
我试图在同一行中打印每个数组的第一列元素[0]和元素[1]连接,第二列元素[0]、元素[1]、元素[2]连接作为第 3 列元素[0]、元素[1]、元素[3] 加入。元素 2 和 3 并不总是存在。
我试图得到的输出是这样的:
AB
CD CDF CDG
HI HIJ
我正在这样做,但我收到了这个错误。
letters.map{|x| puts x[0]+x[1] + "," + x[0]+x[1]+x[2] + "," + x[0]+x[1]+x[3]}
TypeError: no implicit conversion of nil into String
from (irb):1915:in "+"
from (irb):1915:in "block in irb_binding"
from (irb):1915:in "map"
from (irb):1915
from /usr/bin/irb:11:in "<main>"
看起来你想加入前两个字母,然后对剩余的字母进行笛卡尔积。
letters.each do |arr|
first = arr.take(2).join
rest = arr.drop(2)
puts [first, [first].product(rest).map(&:join)].join(" ")
end
这提供了您指定的准确输出。
letters.each do |a,b,*rest|
puts rest.each_with_object([a+b]) { |s,arr| arr << arr.first + s }.join(' ')
end
打印
AB
CD CDF CDG
HI HIJ
步骤如下
假设
letters = [["C", "D", "F", "G"],["H", "I", "J" ]]
然后
enum0 = letters.each
#=> #<Enumerator: [["C", "D", "F", "G"], ["H", "I", "J"]]:each>
生成此枚举器的第一个元素并传递给块,并为三个块变量赋值。
a, b, *rest = enum0.next
#=> ["C", "D", "F", "G"]
a
#=> "C"
b
#=> "D"
rest
#=> ["F", "G"]
接下来,我们得到
enum1 = rest.each_with_object([a+b])
#=> rest.each_with_object(["CD"])
#=> #<Enumerator: ["F", "G"]:each_with_object(["CD"])>
生成此枚举器的第一个元素并传递给块,块变量被赋值。
s, arr = enum1.next
#=> ["F", ["CD"]]
s
#=> "F"
arr
#=> ["CD"]
现在执行块计算。
arr << arr.first + s
#=> arr << "CD" + "F"
#=> ["CD", "CDF"]
生成 enum1
的第二个也是最后一个元素并传递给块,块变量被赋值并计算块。
s, arr = enum1.next
#=> ["G", ["CD", "CDF"]]
arr << arr.first + s
#=> ["CD", "CDF", "CDG"]
当尝试从 enum1
生成另一个元素时,我们获得
enum1.next
#StopIteration: iteration reached an end
Ruby 通过跳出块并返回 arr
来处理异常。然后加入 arr
的元素:
arr.join(' ')
#=> "CD CDF CDG"
并打印出来。
现在生成enum0
的第二个也是最后一个元素,传递给块,三个块变量赋值。
a, b, *rest = enum0.next
#=> ["H", "I", "J"]
a
#=> "H"
b
#=> "I"
rest
#=> ["J"]
其余计算类似。
有些读者可能不熟悉Enumerable#each_with_object这种被广泛使用的方法。阅读文档,但请注意,这里它产生的结果与如下代码编写的结果相同。
letters.each do |a,b,*rest|
arr = [a+b]
rest.each { |s| arr << arr.first + s }
puts arr.join(' ')
end
通过使用 each_with_object
,我们避免了对语句 arr = [a+b]
和语句 puts arr.join(' ')
的需要。这两个语句的功能当然在使用 each_with_object
的行中,但是大多数 Ruby 用户更喜欢当 chaining each_with_object
到join(' ')
。另一个区别是 arr
的值被限制在 each_with_object
的块中,这是一个很好的编程习惯。
出于好奇,Enumerable#map
-唯一的解决方案。
letters = [["A", "B"],["C", "D", "F", "G"],["H", "I", "J" ]]
letters.map do |f, s, *rest|
rest.unshift(nil).map { |l| [f, s, l].join }.join(' ')
end.each(&method(:puts))
#⇒ AB
# CD CDF CDG
# HI HIJ