Ruby: multidimensional array for one-dimensional strings

In Ruby, how can I go from this:

[
  1, 
  ["green", "blue", "black"], 
  [ ["1", "2"], ["3"], ["4", "5"] ]
]

to that?

[
  [1, "green", "1"],
  [1, "green", "2"],
  [1, "blue", "3"],
  [1, "black", "4"],
  [1, "black", "5"],
]

I tried .zip but no luck. Any help is greatly appreciated, and of course I'm looking for the perfect solution.

+4
source share
3 answers

I needed a more general and flexible solution compared to the proposed ones (my bad one, I had to understand the requirements more clearly), so I came up with the following:

class Array
  def transpose_rows
    arys = self.select{|el| el.is_a?(Array)}
    if arys.size == 0
      [self]
    else 
      result = []
      (arys.map(&:size).max || 1).times.map{ |i|
        self.map { |r| 
          r.is_a?(Array) ? r[i] : r
        }.transpose_rows.map{|r| result << r}
      }
      result
    end
  end
end

, . "" -1 "-". , , .

, , , , :

[
  2, 
  [3,4,5], 
  6, 
  [7,8,9], 
  [ [11,22], [33], [44,55] ], 
  [0, 1, 2],
  [ [66], [77], [nil,99] ],
  4
].transpose_rows

# => [
#   [2, 3, 6, 7, 11, 0, 66, 4], 
#   [2, 3, 6, 7, 22, 0, nil, 4], 
#   [2, 4, 6, 8, 33, 1, 77, 4], 
#   [2, 5, 6, 9, 44, 2, nil, 4], 
#   [2, 5, 6, 9, 55, 2, 99, 4]
# ]
+1

, :

data[1].
  zip(data[2]).
  flat_map { |x, ys| [x].product(ys) }.
  map { |zs| [data[0], *zs] }
#=> [[1, "green", "1"], [1, "green", "2"], [1, "blue", "3"], 
#    [1, "black", "4"], [1, "black", "5"]]
+3

arr = [1, ["green", "blue", "black"], [ ["1", "2"], ["3"], ["4", "5"] ]]

.

# 1

arr[1].flat_map.with_index { |color,i| [arr[0]].product([color], arr[2][i]) }
  #=> [[1, "green", "1"], [1, "green", "2"], [1, "blue", "3"],
  #    [1, "black", "4"], [1, "black", "5"]]

.

enum0 = arr[1].flat_map
  #=> #<Enumerator: ["green", "blue", "black"]:flat_map>
enum1 = enum0.with_index
  #=> #<Enumerator: #<Enumerator: ["green", "blue", "black"]:flat_map>:with_index>

enum1 . , enum1 , .

enum1.to_a
  #=> [["green", 0], ["blue", 1], ["black", 2]]

, - .

color, i = enum1.next
  #=> ["green", 0]
color
  #=> "green"
i #=> 0
[arr[0]].product([color], arr[2][i])
  #=> [1].product(["green"], )
  #=> [[1, "green", "1"], [1, "green", "2"]]

, enum1.

An alternative to this is dup arr[2]and dup offset elements:

a2 = arr[2].dup
arr[1].flat_map { |color,i| [arr[0]].product([color], a2.shift) }

# 2

arr[1].zip(arr[2]).flat_map { |color, a| [arr[0]].product([color], a) }
  #=> [[1, "green", "1"], [1, "green", "2"], [1, "blue", "3"],
  #    [1, "black", "4"], [1, "black", "5"]]

Following are the steps.

b = arr[1].zip(arr[2])
  #=> [["green", ["1", "2"]], ["blue", ["3"]], ["black", ["4", "5"]]]

b[0]flat_mapBlock variables are transferred to and assigned, and block calculation is performed.

color, a = b[0]
  #=> ["green", ["1", "2"]]
color
  #=> "green"
a #=> ["1", "2"]
[arr[0]].product([color], a)
  #=> [["1"]].product(["green"], ["1", "2"])
  #=>  [[1, "green", "1"], [1, "green", "2"]]

After the remaining elements are bpassed in map, the desired array is returned List # flat_map .

+2
source

Source: https://habr.com/ru/post/1685796/


All Articles