在Ruby中的同一行中打印不同大小数组的数组元素
Posted
技术标签:
【中文标题】在Ruby中的同一行中打印不同大小数组的数组元素【英文标题】:Print elements of array of arrays of different size in same line in Ruby 【发布时间】:2018-05-18 22:59:40 【问题描述】:也许有人可以帮我解决这个问题。我有一个数组数组。内部数组有不同的大小(从 2 到 4 个元素)。
letters = [["A", "B"],["C", "D", "F", "G"],["H", "I", "J" ]]
我试图在同一行中打印每个数组作为第一列元素 [0] 和元素 [1] 加入,作为第二列元素 [0]、元素 [1]、元素 [2] 作为第三列加入列元素[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>"
【问题讨论】:
【参考方案1】: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 用户更喜欢将each_with_object
链接到join(' ')
时的流程。另一个区别是arr
的值仅限于each_with_object
的块,这是一种良好的编程习惯。
【讨论】:
感谢 Cary Swoveland,它工作得很好。我有点难以理解其中的逻辑。如果有机会和时间,如果您能解释一下它是如何工作的,我将不胜感激。 怀疑,我已经提供了你要求的解释。如果您是 Ruby 新手,则值得仔细研究。 非常感谢 Cary Swoveland。感谢您的详细解释。是的,我是 ruby 新手,并逐步阅读您的内容。我承认我仍然有待完全理解这些步骤的一部分,但对所有看到它的人都非常有用。 怀疑,我在答案的末尾添加了更多解释。 我有问题要理解each_with_object
,通过您的解释,我更好地理解了逻辑以及您使用它的原因。感谢您帮助您与他人分享您的知识,真的【参考方案2】:
看起来你想加入前两个字母,然后用剩下的取笛卡尔积。
letters.each do |arr|
first = arr.take(2).join
rest = arr.drop(2)
puts [first, [first].product(rest).map(&:join)].join(" ")
end
这提供了您指定的确切输出。
【讨论】:
嗨,马克,非常感谢您的帮助。它工作完美。很高兴在实践中学习新事物,例如取放。除此之外,地图(&:join)
中的这种表达式是如何命名的以及它是如何工作的?
map(&:join)
是 map|x| x.join
的简写。【参考方案3】:
出于好奇,Enumerable#map
-only 解决方案。
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
【讨论】:
mudasobwa 谢谢,谢谢,非常感谢收到解决此问题的另一种方法。它有助于学习。以上是关于在Ruby中的同一行中打印不同大小数组的数组元素的主要内容,如果未能解决你的问题,请参考以下文章
C 找数组中最小的元数,找出最小数下标并返回,在主函数中打印最小数和下标?