0

也许有人可以帮我解决这个问题。我有一个数组数组。内部数组有不同的大小(从 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>"
4

3 回答 3

2
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 通过跳出块并返回来处理异常arrarr然后加入的元素:

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(' ')。这两个语句的功能当然在 using 行中,但是大多数 Ruby 用户在链接each_with_object时更喜欢流。另一个区别是 ' 的值仅限于' 块,这是良好的编程习惯。 each_with_objectjoin(' ')arreach_with_object

于 2018-05-19T02:38:59.327 回答
1

看起来你想加入前两个字母,然后用剩下的取笛卡尔积。

letters.each do |arr|
   first = arr.take(2).join
   rest = arr.drop(2)
   puts [first, [first].product(rest).map(&:join)].join(" ")
end

这提供了您指定的确切输出。

于 2018-05-19T00:31:17.207 回答
1

只是出于好奇,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
于 2018-05-19T04:19:54.390 回答