Вывести элементы массива массивов разного размера в одной строке в Ruby - PullRequest
0 голосов
/ 19 мая 2018

Может быть, кто-то может помочь мне с этим.У меня есть массив массивов.Внутренние массивы имеют разные размеры (от 2 до 4 элементов).

letters = [["A", "B"],["C", "D", "F", "G"],["H", "I", "J" ]] 

Я пытаюсь напечатать в одной строке каждый массив, к которому относится первый элемент столбца [0] и элемент [1], как элемент 2-го столбца [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>"

Ответы [ 3 ]

0 голосов
/ 19 мая 2018
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, что является хорошей практикой программирования.

0 голосов
/ 19 мая 2018

Просто из любопытства, 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
0 голосов
/ 19 мая 2018

Похоже, вы хотите соединить первые две буквы, а затем взять декартово произведение с оставшимися.

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

Это обеспечивает точный вывод, который вы указали.

...