2016-06-29 24 views
2

オブジェクトの配列があり、その多くは配列に何回も表示されます。 1つのアイテムの特定の場所へのインデックスがあります。私はインデックスを維持しながら、すべての場所で配列から1つのオブジェクトを削除したい。削除されたアイテムへのインデックスは、次に使用可能なアイテムに移動し、存在しない場合は、配列の先頭に折り返さなければなりません。配列を保持するインデックスからアイテムを削除する

array = [:b, :a, :b] 
index = 2 

今すぐ配列から:aを削除し、第二:bがあるので、インデックスは今、1を次のようになります。

私は、私は非常によくそれを説明していないと思うので、ここで簡単な例を示します現在インデックス1に設定されています。

インデックスが削除されたオブジェクトを指しているとしましょう。インデックスは、次に使用可能なオブジェクトに移動する必要があります。したがって、インデックスが1の場合は、:bを指しており、すぐ後に:aが続きますので、インデックスは変更されません。

ここではラップアラウンド例です:あなたは:aを削除した場合、インデックスは次の使用可能なインデックスにラップアラウンドする必要があり、または0

はシンプルようだが、はるかに複雑なエッジケースがある

array = [:b, :a] 
index = 1 

。削除した後

array = [:a, :a, :b, :a, :c, :b, :a] 

:ここで私は考えることができる最も複雑な例です「:A」、結果の配列は[:b, :c, :b]です。彼らは0、0、0、1、1、2に変更する必要があり、すべての可能な開始インデックス(0~6)から、0

は、アレイ内の複数のオブジェクトが存在すると仮定し、それは、削除後の空になることはありません。

(編集)私は私がこれまで試したものを含むべきであることを私に知らせるための@Raffaelへ

感謝。ここに私の最初の試みがあった:

  • @itemsは配列です。
  • @current_item_indexは、調整が必要な指標です。
  • itemは削除されるアイテムです。

コード:

indexes = @items.each_index.each_with_object([]) do |i, memo| 
    memo << i if @items[i] == item 
end 

indexes.reverse.each do |i| 
    @items.delete_at(i) 
    @current_item_index -= 1 if i < @current_item_index 
    @current_item_index = 0 unless @current_item_index < @items.size 
end 

それだけで非常に "ルビー"(クリアも簡潔ではないが)いないようでした。また、それはリストを2回実行するので、それほどパフォーマンスが良いようには見えません - 良いことはできないすべてのそれらのdelete_atの呼び出しはもちろんです。

+1

なぜこれを行うのですか。つまり、使用状況は何ですか?あなたの最終目標を達成するためのより良い方法はないでしょうか? – pjs

+0

あなたは40分以上前にこの質問をしました。答えはなく、コメントは1つだけです。つまり、誰もあなたの質問を理解することはできません。あなたの最初の例では、 'index = 2'であっても、インデックス1にある':a'を削除します。あなたがそうするように導くルールは何ですか? 'index-1'で要素を削除していたと思います。しかし、第2の例では、 'index = 1'のときに':b'が削除されることを期待していましたが、インデックス 'index - 1#=> 0'にあるので、' 'a''インデックス1、それは削除されます。明確にするために質問を編集してください。 –

+1

@pjs:現在のプレーヤーを追跡するインデックスを持つ、ゲーム内のプレーヤーのリストがあります。プレイヤーは複数のターンを持つことがあるので、アレイに複数回いる。このアルゴリズムは、プレイヤーがゲームを終了するときに実行されるように意図されています。私は、より良いものが提示されれば、表現をリファクタリングすることに完全にオープンです。 –

答えて

1

新しいインデックスが

  • が古いインデックスの前に配置されていることを古い配列の要素数に等しい

あなたが数えることができる配列のままになりますこれらのように新しい配列を構築しながら移動しながら:

def delete_and_follow(old_array, old_index, unwanted) 
    new_array, new_index = [], 0 
    old_array.each.with_index do |item, idx| 
    unless item == unwanted 
     new_array << item 
     new_index += 1 if idx < old_index 
    end 
    end 
    new_index = 0 if new_index >= new_array.length 
    [new_array, new_index] 
end 

または同じウィットhコードが少ないです(少しはっきりしていますが)。

def delete_and_follow(old_array, old_index, unwanted) 
    new_index = old_array.take(old_index).count{ |item| item != unwanted } 
    new_array = old_array - [unwanted] 
    [new_array, new_index % new_array.length] 
end 

HTH!

+0

これは、 'old_array' in-placeを変更しないことに注意してください。あなたがインプレースを好むなら教えてください。 – Raffael

+0

これは良いですね。私は、古いアレイとインデックスを置き換えたばかりです。私の元の試みはその場で行われていて、それはかなり醜いものでした。 –

関連する問題