【Ruby】配列の複数要素の削除はdelete_ifかrejectを使おう

zomです。
< 2013/04/10 タイトル修正しました >
Rubyの実装で「よく考えればそうだよね」ということがあります。
最近あったところで、掲題のことが言えます。
経緯とかをちょっとメモがてら書いておきます。

Rubyで配列があったとします。この中で、特定の文字列を含む要素を1つだけ削除したいです。
それであればArray.delete(‘特定の文字列’)で済みます。
ただし、その特定の文字列というのが複数ある場合はどうしましょう?
複数あるなら、それを配列にでも突っ込んで、イテレートしてdeleteしていけばいいじゃない。
と考えたのが以下の実装です。

なんとbean(豆)が残ってしまっています!(あえて大袈裟に書いてます笑)
よく考えれば、分かることかもしれませんが、イテレートしている最中に要素を削除することで内部ポインタがずれてしまうのです。
ここの例だと配列の0番目はasuparagusです。最初のループでstrにはasuparagusが入り、
list_include?にかけられてtrue、target.deleteが実行されます。
その直後にtarget[0]をprintしてみると、beanが入っています。

ということで、配列の場合はポインタが狂ってしまうので、削除にeach&deleteを使うのはオススメしない!という話です。
こういうこともあるので用意されているのが、delete_if、rejectメソッドということなんですね。
delete_ifやrejectメソッドはこういうことがおきません。
用意されているにはそれなりにワケがあるって感じですねー。

投稿者:

zom

都内でプログラマやってるアラサーの男性です。 このブログは日記とか書いてます。ゆるーくやってます。かるいオタクです。 パズドラ/クラクラ/ケリ姫/にゃんこ大戦争あたりをよくやってます。 以下、人名は敬称略。音楽大好き。平沢進、ヒトリエ、FinalFantasyあたりのコンサート・ライブによく行きます。マンガも大好きです。作者で言うと日本橋ヨヲコ、水上悟志あたり。

「【Ruby】配列の複数要素の削除はdelete_ifかrejectを使おう」への2件のフィードバック

  1. マイナス演算子で配列の差集合を求められますよ

    target = [‘asparagus’, ‘bean’, ‘carrot’] # 元となるデータ
    list = [‘asparagus’, ‘bean’] # 削除対象の文字列のリスト
    target – list #=> [“carrot”]

    1. ホントですね!
      Rubyはいろんなやり方で同様の処理が実現できるので、性格とか表れそうですよね。

コメントを残す

メールアドレスが公開されることはありません。