2017-01-20 14 views
1

希望の列インデックスを取り、それらの列だけを持つ2次元配列を返す2次元配列をフィルタリングしたいと思います。空の配列を除いて、私は同じ2次元配列を返したいと思います。副作用のない2次元配列をフィルタリングする

また、元の配列を変更したくないので、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"]] 

答えて

1

これは行列のコピーを作成し、この

matrix.map(&:dup) 

をお試しください:

以下は私のソリューションです。


プロティップ - あなたのコードでは、最も内側のループ内の各要素について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 
+0

+1私の投票権があるときは、プロのヒントのために+1します。あなたは例を挙げることができますか?また、あなたのテクニック 'matrix.dup.map(&:dup)'が[この質問]に当てはまると思いますか?(http://stackoverflow.com/questions/41657091/use-replace-to-make-a-copy -of-an-array)? – mbigras

+0

その質問には1次元配列しかありません。 'matrix.map(&:dup)'の2次元配列が正しい場合、マーシャリングコードは、実際には起こりたくない行列の要素も複製します。 – akuhn

+1

ありがとう@akuhn! '(columns)'を '(* columns)'に変更できますか? :) – mbigras

2

あなたはHash#values_atの前と後のArray#transposeを使用することができます。

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は変更されていないことに注意してください。