过滤2维数组,没有副作用

时间:2017-01-20 22:17:12

标签: arrays ruby multidimensional-array

我想过滤一个采用所需列索引的二维数组,并返回仅包含那些列的二维数组。除了一个空数组,我想返回相同的二维数组。

另外我不想修改原始数组,并且我想编写没有任何if语句的代码,或者尽可能地限制分支。

我想知道Marshal#loadMarshal#dump是否多余,并使用#map!

我选择使用#map!的原因是我不必使用if..else..end块,但我很想学习其他策略。

以下是我的解决方案:

def keep_columns args
  matrix = Marshal.load Marshal.dump args[:matrix]
  columns = args[:columns]
  matrix.map! do |row|
    row.select.with_index { |_,idx| columns.include? idx }
  end unless columns.empty?
  matrix
end

matrix = [['foo','bar', 'baz'],['cats', 'and', 'dogs']]

keep_columns matrix: matrix, columns: [0,2]
#=> [["foo", "baz"], ["cats", "dogs"]]
keep_columns matrix: matrix, columns: []
#=> [["foo", "bar", "baz"], ["cats", "and", "dogs"]]

2 个答案:

答案 0 :(得分:2)

您可以在Array#transpose之前和之后使用Hash#values_at

def extract_columns(arr, columns)
  return arr if columns.empty?
  arr.transpose.values_at(*columns).transpose
end

arr = [['foo','bar', 'baz'],['cats', 'and', 'dogs']]

extract_columns(arr, [0, 2])
  #=> [["foo", "baz"], ["cats", "dogs"]] 
extract_columns(arr, [])
  #=> [["foo", "bar", "baz"], ["cats", "and", "dogs"]]

请注意,arr未被修改。

答案 1 :(得分:1)

试试这个

matrix.map(&:dup)

这会创建矩阵的副本。

Pro tipp - 您的代码对最内层循环中的每个元素进行columns线性搜索,可能会使用row.values_at(*columns)代替?

def keep_columns(args)
  columns, matrix = args.values_at(:columns, :matrix)
  return matrix.map(&:dup) if columns.empty?
  matrix.map { |row| row.values_at(*columns) }
end