値から配列から1つの要素を削除するにはどうすればよいですか


343

Rubyに要素の配列があります

[2,4,6,3,8]

3たとえば、値を持つ要素を削除する必要があります

それ、どうやったら出来るの?


delete array.delete(3)Ruby on Railsコントローラー内で機能しないのはなぜでしょうか
ImranNaqvi 2016年

2
active recordメソッドが原因である可能性がありますdelete
ImranNaqvi 2016年

回答:


481

私はそれを理解したと思います:

a = [3, 2, 4, 6, 3, 8]
a.delete(3)
#=> 3
a
#=> [2, 4, 6, 8]

189
私が個人的に気に入っ[1, 2, 3, 4, 5] - [3]ているのは、=> [1, 2, 4, 5]からの結果irbです。
Travis

24
3のエントリが複数あり、そのうちの1つだけを削除したい場合はどうなりますか?(これは関連しているので、ここで質問するのが最善かもしれません)
Navneet

113
.delete()は、値を削除した変更された配列ではなく、削除された値を返すことを示しています。
Joshua Pinter 2013

23
考慮すべきもう1つの結果はdelete、基になる配列を変更するのに対して-、削除された値なしで新しい配列(ユーザーに返される)を作成することです。ユースケースに応じて、どちらのアプローチも意味があります。
srt32

2
@ user3721428、delete(3)は位置3の要素を参照せず、代わりに整数3に一致する要素を削除します。これにより、3のすべての出現が削除され、配列のインデックスまたは位置とは関係ありません。
bkunzi01

226

コメントでTravisから借りて、これはより良い答えです:

私個人的には同様[1, 2, 7, 4, 5] - [7]で結果=> [1, 2, 4, 5]からirb

3が彼のサンプル配列の3番目の要素であることを確認して、私は彼の答えを変更しました。これは、3が配列の2の位置にあることに気付いていない人に混乱を招く可能性があります。


21
srt32が答えで指摘しているように、との使用には重要な違いが.deleteあり-ます。.delete存在する場合は、配列から削除された値を返します。-しない。だから、[ 1, 2, 3 ] - [ 2 ]戻ります[ 1, 3 ]が、[ 1, 2, 3 ].delete( 2 )返されます2
Argus9 2014年

5
array - subArrayArray of Arraysでは機能しませんが、機能しarray.delete(subArray)ます。
Sachin

20
間の非常に重要な違い[1,2,3] - [2][1,2,3].delete(2)それであるdelete方法は、元の配列を変更しながらは、[1,2,3] - [3]作成する新しいアレイ
ティモシーコバレフ2016年

サブアレイ再(上記のサチンさんのコメント@)「確かにそれはします」、あなただけの表記権を取得する必要があります: [1,2,[2],2,3,4] - [2]あなたを与える[1, [2], 3, 4]が、[1,2,[2],2,3,4] - [[2]]あなたを与えます[1, 2, 2, 3, 4]。:-)
トムHundt


50

誰かがこれを述べたかどうかはわかりませんが、Array.delete()と-= valueは、配列内で渡された値のすべてのインスタンスを削除します。特定の要素の最初のインスタンスを削除するには、次のようにします

arr = [1,3,2,44,5]
arr.delete_at(arr.index(44))

#=> [1,3,2,5]

もっと簡単な方法があるかもしれません。これがベストプラクティスであると言っているわけではありませんが、認識すべきものです。


1
これを行う方法を探していて、重複した場合に要素のインスタンスを1つだけ削除しました。これはうまくいきます!
xeroshogun 2017年

私はこの答えは間違っていると思います、arr.index()が行く可能性があるからですnil
windmaomao

32

配列内の複数の場所で3 by valueを削除する場合、このタスクを実行するrubyの方法は、delete_ifメソッドを使用することだと思います。

[2,4,6,3,8,3].delete_if {|x| x == 3 } 

「配列の配列」のシナリオで要素を削除するときにdelete_ifを使用することもできます。

これでクエリが解決することを願っています


25

-=[4]値が4の要素を削除するには、他の回答で述べた方法が好きです。

しかし、この方法があります:

irb(main):419:0> [2,4,6,3,8,6].delete_if{|i|i==6}
=> [2, 4, 3, 8]
irb(main):420:0>

関数について言及した後、「基本的な配列操作」のどこかで言及しましたmap


しかし、ただ使用することはできません.delete(6)
Zac

もちろん、@ Zacですが、その答えは既に言及されています(非常に簡潔な-=方法、 a-=[4]つまりa=a-[4][3,4]-[4]、私が好きだと言ったように)が、別の可能な方法について言及したいと思いました。
2016年

このメソッドには、削除された要素の代わりに配列を返すという利点もあります。
F.Webber



15

ここにいくつかのベンチマークがあります:

require 'fruity'


class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8]

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 4096 times. Test will take about 2 seconds.
# >> soziev is similar to barlop
# >> barlop is faster than steve by 2x ± 1.0
# >> steve is faster than rodrigo by 4x ± 1.0
# >> rodrigo is similar to niels

繰り返しになりますが、多くの重複を含む大きな配列を使用します。

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 1000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 16 times. Test will take about 1 second.
# >> steve is faster than soziev by 30.000000000000004% ± 10.0%
# >> soziev is faster than barlop by 50.0% ± 10.0%
# >> barlop is faster than rodrigo by 3x ± 0.1
# >> rodrigo is similar to niels

そして、より多くの重複でさらに大きくなります:

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 100_000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test once. Test will take about 6 seconds.
# >> steve is similar to soziev
# >> soziev is faster than barlop by 2x ± 0.1
# >> barlop is faster than niels by 3x ± 1.0
# >> niels is similar to rodrigo

7
では、何が一番良いのでしょうか?:)
カービー

8

Nielsのソリューションを改善しました

class Array          
  def except(*values)
    self - values
  end    
end

今、あなたは使うことができます

[1, 2, 3, 4].except(3, 4) # return [1, 2]
[1, 2, 3, 4].except(4)    # return [1, 2, 3]

ソリューションがirbコンソールで 機能しない2.2.1 :007 > [1, 2, 3, 4].except(3, 4) NoMethodError: undefined method except for [1, 2, 3, 4]:Array from (irb):7 from /usr/share/rvm/rubies/ruby-2.2.1/bin/irb:11:in <main>
hgsongra 2016

1
IRBで宣言するには、メソッドをArrayに追加する必要がありますclass Array; def except(*values); self - values; end; end
Mark Swardstrom 2017年

3

サルにパッチを当てることもできます。Rubyに次のようなexceptメソッドがある理由を理解HashできませんでしたArray

class Array
  def except value
    value = value.kind_of(Array) ? value : [value]
    self - value
  end
end

今あなたはできる:

[1,3,7,"436",354,nil].except(354) #=> [1,3,7,"436",nil]

または:

[1,3,7,"436",354,nil].except([354, 1]) #=> [3,7,"436",nil]

1
value.kind_of(Array)テストは必要ありません。だけを使用してくださいself - Array(value)
Sasgorilla 2017年

3

したがって、3の複数のオカレンスがあり、3の最初のオカレンスのみを削除したい場合は、次のように簡単に行うことができます。

arr = [2, 4, 6, 3, 8, 10, 3, 12]

arr.delete_at arr.index 3

#This will modify arr as [2, 4, 6, 8, 10, 3, 12] where first occurrence of 3 is deleted. Returns the element deleted. In this case => 3.

3

最初の発生の非破壊的な除去:

a = [2, 4, 6, 3, 8]
n = a.index 3
a.take(n)+a.drop(n+1)

2

この削除操作を連鎖可能にして、一部のアイテムを削除し、結果の配列の操作を連鎖し続けたい場合は、次を使用しますtap

[2, 4, 6, 3, 8].tap { |ary| ary.delete(3) }.count #=> 4

1

Rubyでの削除のさまざまなオプションのコンパイル

削除 -削除が値によって要素に一致します。複数の値が一致する場合は、すべて削除されます。発生回数を気にしない場合、または1回のみ発生する場合は、このメソッドを使用します。

a = [2, 6, 3, 5, 3, 7]
a.delete(3)  # returns 3
puts a       # return [2, 6, 5, 7]

delete_at-指定されたインデックスの要素を削除します。インデックスがわかっている場合は、このメソッドを使用します。

# continuing from the above example
a.delete_at(2) # returns 5
puts a         # returns [2, 6, 7]

delete_if-ブロックがtrueであるすべての要素を削除します。これにより、アレイが変更されます。ブロックが呼び出されると、配列は即座に変化します。

b = [1, 2, 5, 4, 9, 10, 11]
b.delete_if {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]

reject-これは、指定されたブロックがfalseである要素を持つ新しい配列を返します。これにより、順序が維持されます。

c = [1, 2, 5, 4, 9, 10, 11]
c.reject {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]

拒否!-delete_ifと同じです。ブロックが呼び出されても、配列はすぐには変更されません。

配列から複数の値を削除する場合は、次の方法が最適です。

a = [2, 3, 7, 4, 6, 21, 13]
b = [7, 21]
a = a - b    # a - [2, 3, 4, 6, 13]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.