反转多维数组 - 函数式编程风格

时间:2016-07-21 19:34:59

标签: arrays ruby multidimensional-array collections functional-programming

我很难用一种功能性方法来反转Ruby中的多维(偶数维)数组。 输入:[[1,2,3],[4,5,6],[7,8,9]] 输出:[[7,4,1],[8,5,2],[9,6,3]]

这种迭代解决方案有效。

def reverse(arr)
  size = arr.length
  output = Array.new(size) { Array.new(size,0) }
  arr.reverse.each_with_index do |a, i|
    a.each_with_index do |a, j|
      output[j][i] = a
    end
  end
  output
end

任何人都对如何使用更多函数式编程风格并且没有引用显式索引有任何见解?

3 个答案:

答案 0 :(得分:6)

如果array是您的输入,那么它就像

一样简单
result = array.transpose.map(&:reverse)

如果我正确理解您所需的输出。 ;)

详细说明:Array#transpose基本上“镜像”沿主对角线的2D阵列:

transposed = array.transpose  #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

您似乎只想要反转所有行,这是通过调用map来处理的:

result = transposed.map(&:reverse)  #=> [[7, 4, 1], [8, 5, 2], [9, 6, 3]]

map(&:reverse)语法只是map { |a| a.reverse }的简写,并由this方法启用。

手动完成

在我的初步回答之后,评论中发现OP实际上是在transpose的功能实现之后。以下是我提出的建议:

def transpose(a)
  (0...a[0].length).map { |i|
    (0...a.length).map { |j| a[j][i] }
  }
end

虽然这确实引用了显式索引,但它是由其他纯函数组成的纯函数,因此它至少符合 my 函数的定义。 ;)

答案 1 :(得分:3)

ar =  [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

ar.reverse.transpose # => [[7, 4, 1], [8, 5, 2], [9, 6, 3]]

答案 2 :(得分:3)

arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

arr_rev = arr.reverse
  #=> [[7, 8, 9], [4, 5, 6], [1, 2, 3]] 
arr_rev.first.zip *arr_rev[1..-1]
  #=> [[7, 4, 1], [8, 5, 2], [9, 6, 3]] 

我认为这符合functional programming的要求。

步骤:

arr_rev = arr.reverse
   #=> [[7, 8, 9], [4, 5, 6], [1, 2, 3]] 
arr_rev.first.zip(arr_rev[1..-1])
   #=> [7, 8, 9].zip(*[[4, 5, 6], [1, 2, 3]])
   #.    [7, 8, 9].zip([4, 5, 6], [1, 2, 3])
   #.    [[7, 4, 1], [8, 5, 2], [9, 6, 3]]

请参阅Enumerable#zip