2016-06-17 2 views
0

これで配列の配列があります。より大きな配列内の各配列は、非常に同じ10個の特定の値です。位置3の私の値が特定の値であれば、大きな配列内の残りの残りの配列を反復し、位置0,1、および2の最初の3つの値が一致するかどうかを確認します。それらが一致する場合、私は元の配列を削除したいと思います。私はそれで苦労している、おそらく簡単な方法がありますか?私は)私は=この全体のコーディングのものにかなり新たなんだ、そこにあることを確認し、あなたの助けを事前にあまりにも多くの感謝だよ....ruby​​ on railsで最初の3つの値が一意でない場合、多次元配列から配列を削除します。

私がでてるのはここです:

@projectsandtrials.each do |removed| 
    if removed[3] == ["Not Harvested"] 
    @arraysforloop = @projectsandtrials.clone 
    @arraysforloop1 = @arraysforloop.clone.delete(removed) 
    @arraysforloop1.each do |m| 
     if (m & [removed[0], removed[1], removed[2]]).any? 
     @projectsandtrials.delete(removed) 
     end 
    end 


    end 

end 
+0

私の問題は、最初の配列が@projectsandtrialsから削除されていて、それは...ではないはずですが、他のすべては問題ありません。 – bwatson30

+0

目的の結果を含む小さな例を挙げて編集してください。配列のサイズは10でなく、5つの要素を小さくします。あなたが望むなら、私が私の答えで与えた例を自由に使ってください。 –

答えて

3

できますあなたの状況を見てください:

@projectsandtrials.each do |removed| 
    // some logic, yada yada 
    @projectsandtrials.delete(removed) 
end 

反復処理中の配列から削除することはできません。あなたがそれを反復し終えるまで、少なくとも。代わりに、eachの代わりにrejectのようなフィルタリング方法を使用する必要があります。

そこで、削除する代わりに、拒否を使用する場合はtrueを返す必要があります。

配列を反復するときは、このように考えるのです。

配列を同じサイズにして同じ内容にしたいですか? eachを使用してください。

アレイのサイズは同じですが、内容は異なりますか? mapを使用してください。

配列を現在のサイズ以下にしたいですか? selectまたはrejectを使用してください。

最終的に単一の値にしたいですか? reduceを使用してください。

+0

おかげさまで、@arjabbarさん、そして他のみんながこの問題に取り組んでいます。私の初期の解決策はかなりシンプルでした。あなたが言うように、私は繰り返しを終えるまで私の配列を削除するのを待つ必要がありました。それはうまくいきましたが、私は先に進み、それをきれいにしてリジェクトメソッドを使うようにリファクタリングしました!ありがとうございます!常に学習の経験と思考のさまざまな方法を聞いて良い! – bwatson30

0

注意すべき点がいくつもあるがあなたのコードスニペットは、罰金だ:

  1. @arraysforloop.clone.delete(removed)removed配列(最初のものだけではなく)のすべての出現箇所を削除します。例えば。 [1,2,3,1] .delete(1)はあなたに[2,3]を残します。 @projectsandtrialsdelete_atメソッドのイテレータを使って修正できます。

  2. deleteメソッドは、渡すのと同じ引数を返します(一致するものがない場合はnil)。だから@arraysforloop1 = @arraysforloop.clone.delete(removed)はあなたの@arraysforloop1に、削除された配列の要素だけを含むようにします!課題を削除すると、あなたを救うことができます。

  3. クローンアレイが2つある理由はわかりません。@arraysforloop@arraysforloop1は、後で使用されないためです。そのうちの1つを省略することはできますか?

  4. @projectsandtrials.delete(removed)は、今、同じ配列を繰り返し処理している限り、あなたは変な状態に陥ります。これにより、削除された要素の次の要素が欠落してしまうことがあります。それは配列の最初の要素になったと見ての通り、要素1を削除した後、ループが2を省略し、直接要素3に移動

    > a = [1,2,3] 
    > a.each{|e, index| puts("element is: #{e}"); a.delete(1);} 
    element is: 1 
    element is: 3 
    

    (およびアルゴリズムは、それがされています考えて:ここでの動作を説明するための簡単なスニペットですすでに処理されています)。

1つの可能性は、それをメソッドのバンドルに分割することです。

def has_searched_element? row 
    # I leave this method implementation to you 
end 

def next_rows_contain_three_duplicates?(elements, index) 
    # I leave this method implementation to you 
end 

def find_row_ids_to_remove elements 
    [].tap do |result| 
    elements.each_with_index do |row, index| 
     condition = has_searched_element?(row) && next_rows_contain_three_duplicates?(elements, index) 
     result << index if condition 
    end 
    end 
end 

row_ids_to_remove = find_row_ids_to_remove(@projectsandtrials) 
# now remove all the elements at those ids out of @projectsandtrials 
1

コードarrの要素(アレイ)の最後の値が連続していること

def prune(arr, val) 
    arr.values_at(*(0..arr.size-4).reject { |i| arr[i][3] == val && 
    arr[i+1..i+3].transpose[0,3].map(&:uniq).all? { |a| a.size==1 } }. 
     concat((arr.size-3..arr.size-1).to_a)) 
end 

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

注意:ここではオプションです。これは、削除されたprune(arr, 4)(下記)の要素を識別するのに役立ちます。

prune(arr, 4) 
    # => [[3, 4, 5, 6, 1], 
    #  [3, 4, 5, 4, 2], 
    #  [3, 4, 5, 6, 3], 
    #  [3, 4, 5, 6, 4], 
    #  [3, 4, 0, 6, 5], 
    #  [2, 3, 5, 5, 7], 
    #  [2, 3, 5, 7, 8], 
    #  [2, 3, 5, 8, 9], 
    #  [2, 3, 5, 7, 0]] 

説明

指数06におけるアレイは、アレイに返さ含まれていません。すべての[3,4,5]を開始arr[0][3] = val = 4arr[1]arr[2]arr[3]ので

arr[0][1,2,3,4,0])が含まれていません。すべての[2,3,5]を開始arr[6][3] = 4arr[7]arr[8]arr[9]ので

arr[6][2,3,5,4,6])が含まれていません。 (即ち、arr[5][2] = 0arr[2][3] = 4arr[3][0,3]arr[4][0,3]arr[5][0,3]ながらすべてではない全て等しいので

arr[2][3,4,5,5,2])が含まれています。

arrの最後の3つの要素は、常に返される配列に含まれることに注意してください。

ここで、計算を調べてみましょう。最初に以下を考えてみましょう。

arr.size 
    #=> 11 

a = (0..arr.size-4).reject { |i| arr[i][3] == val && 
    arr[i+1..i+3].transpose[0,3].map(&:uniq).all? { |a| a.size==1 } } 
    #=> (0..7).reject { |i| arr[i][3] == val && 
    arr[i+1..i+3].transpose[0,3].map(&:uniq).all? { |a| a.size==1 } } 
    #=> [1, 2, 3, 4, 5, 7] 

i=0(リコールval=4)用rejectのブロック演算を考えます。

意味arr[0]は拒否されます。つまり、返された配列には含まれません。 残りのブロック計算(i=1,...,10の場合)は似ています。

我々は保持される最後の3除くarrのすべての要素のインデックスである

a #=> [1, 2, 3, 4, 5, 7] 

を計算しています。 aには、最後の3つの要素、すなわちarrのインデックスを追加します。

b = a.concat((arr.size-3..arr.size-1).to_a) 
    #=> a.concat((8..10).to_a) 
    #=> a.concat([8,9,10]) 
    #=> [1, 2, 3, 4, 5, 7, 8, 9, 10] 

最後に、

arr.values_at(*b) 

例で与えられた配列を返します。

関連する問題