2010-07-15 12 views
57

Bazı öğeler üzerinde yinelemek ve silmek istediğiniz bir dizi var. Bu işe yaramazsa:Dizide yinelenen Array # delete öğesini nasıl kullanabilirim?

a = [1, 2, 3, 4, 5] 
a.each do |x| 
    next if x < 3 
    a.delete x 
    # do something with x 
end 
a #=> [1, 2, 4] 

Ben [1, 2] olmak a istiyorum. Bunu nasıl aşabilirim?

+0

Olası yinelenen [Ruby'de Yinelenen Sırasında Silme Yapılıyor?] (Http://stackoverflow.com/questions/2933366/deleting-while-iterating-in-ruby) – sschuberth

cevap

101

a.delete_if { |x| x >= 3 }

Bkz yöntemiyle ilgili belgeler here

Güncelleme: Sen blokta x işleyebilir

:

a.delete_if do |element| 
    if element >= 3 
    do_something_with(element) 
    true # Make sure the if statement returns true, so it gets marked for deletion 
    end 
end 
+1

Alırsa x ile bir şeyler yapmam gerekiyor silindi. Bunu bloğa koymalı mıyım? – Adrian

+0

Evet, güncellenmiş yanıtıma bakın – Chubas

+1

@Adrian Ya da 'reddet!' Komutunu kullanabilirsiniz. –

2

Ben bir süre önce bu soru soruldu.

Deleting While Iterating in Ruby?

şey silinmeye çalışılırken Yakut .each döngünün çıkar çünkü çalışmıyor. Eğer diziden birşeyleri silmek istiyorsanız, delete_if çalışacaktır, ancak daha fazla kontrol istiyorsanız, bu iş parçasında sahip olduğum çözüm çok çirkin olsa da işe yarıyor.

+8

Silme işlemi döngüyü kırmaz. 'herbir 'etkili bir şekilde indeksi kullanarak yinelemektedir. Böylece, silerseniz, dizinler farklıdır ve sonraki yineleme yeni dizinleri kullanır. Bunu deneyin: 'arr = [1,2,3,4,5,6]; arr.each_with_index {| e, i | p [arr, e, i]; sonraki e <3 ise; arr.delete e} '. Öğe 3'e ulaşıldığında, dizin 2'dir. 3 silindikten sonra, bir sonraki yineleme, indeksi 3'e artırır ve madde 5'dir. Böylece 4 atlanır. Aynı sebepten 6 tanesi atlandı. – Kelvin

7

Sen diziden silmek zorunda değilsiniz, öyle filtreleyebilirsiniz:

a = [1, 2, 3, 4, 5] 

b = a.select {|x| x < 3} 

puts b.inspect # => [1,2] 

b.each {|i| puts i} # do something to each here 
+0

Bir zombi postasını yükseltmek için üzgünüm, fakat b = bir yaklaşımın alt kümesinin bellek kullanımını artırıp artırmadığını veya iç öğeleri veya orijinal öğelere başvurmak için bir şey kullanıp kullanmadığını merak ediyorum. Benim sorduğum sebep, benim kullanım durumumun, bellekte oldukça hassas olması, orijinal diziden silinip silinmemesi ya da daha iyi bir yöntem olup olmaması ... – gorlaz

2

tartışmasız nettir o reject! kullanıyor yapmanın bir başka yolu, bu "Bu demektir ki bir ! beri diziyi değiştirecek ". Tek fark, hiçbir değişiklik yapılmazsa reject!'un nil dönmesidir.

a.delete_if {|x| x >= 3 } 

veya

a.reject! {|x| x >= 3 } 

çok iyi çalışıyor olacak.