Ruby'de bir Diziyi diğerinden çıkarmak


83

Oluşturulmuş ve atanmış iki Görev dizisi var. Atanan tüm görevleri oluşturulan görevler dizisinden kaldırmak istiyorum. İşte benim çalışmam, ama dağınık, kod:

    @assigned_tasks = @user.assigned_tasks
    @created_tasks = @user.created_tasks

    #Do not show created tasks assigned to self
    @created_not_doing_tasks = Array.new
    @created_tasks.each do |task|
        unless @assigned_tasks.include?(task)
            @created_not_doing_tasks << task
        end
    end

Eminim daha iyi bir yolu vardır. Bu ne? Teşekkürler :-)


İddiaya girerim, cevabın tam da orada kodladığınız şeyi yapmaktır.
baash05

Yanıtlar:


177

Ruby'de dizileri çıkarabilirsiniz:

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

ary - diğer_ary → new_ary Dizi Farkı

Diğer_ariyede de görünen tüm öğeleri kaldırarak, orijinal dizinin bir kopyası olan yeni bir dizi döndürür. Sıra, orijinal diziden korunur.

Öğeleri hash ve eql kullanarak karşılaştırır. verimlilik yöntemleri.

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

Küme benzeri davranışa ihtiyacınız varsa, Küme kitaplık sınıfına bakın.

Dizi belgelerine bakın .


2
Arg. Benim için büyük yüz-palmiye anı. Nedense nesnelerle işe yaramayacağını düşündüm. Gayet iyi çalıştı - teşekkürler!
doctororange

28
buna dikkat edin, önce IRB'de test edin, örneğin: [5, 5, 5, 5] - [5, 5] = [] ... çıkarma, dizideki benzersiz öğeleri kaldırır.
hagope

9
Ayrıca, bu olmaz şekilde çalıştığını unutmayın: [1,2]-[1,2,3] => []. Ama [1,2,3]-[1,2] => [3]. Argh.
Zabba

17
Çıkarma açısından düşünürseniz, bu son "aldatma" aslında mantıklıdır. To çıkarma Eğer talep etmiyoruz şey fark ... Eğer Y bile X şey varsa o zaman sonuç tür 'tanımsız', dolayısıyla ekstra Y eleman gitmeyeceklerini ait olduğunu ... X, Y çıkarmak istiyoruz X sonucuna dahil edilmez.
Bane

2
Spesifik olarak, Array#-bir set farktır. Bu , birleştirme işleminden Array#|daha çok bir set birleşiminin tersidir Array#+(hiç bir set işlemi değil!).
ymbirtt

9

Yukarıdaki çözüm

a - b

dizideki elementlerin tüm örneklerini siler bdiziden a.

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

Bazı durumlarda sonucun olmasını istersiniz [1, 2, 3, 3, 5]. Yani, tüm kopyaları değil, yalnızca öğeleri tek tek silmek istemezsiniz.

Bunu şu şekilde başarabilirsin

class Array
  def delete_elements_in(ary)
    ary.each do |x|
      if index = index(x)
        delete_at(index)
      end
    end
  end
end

Ölçek

irb(main):198:0> a = [ 1, 1, 2, 2, 3, 3, 4, 5 ]
=> [1, 1, 2, 2, 3, 3, 4, 5]
irb(main):199:0> b = [ 1, 2, 4 ]
=> [1, 2, 4]
irb(main):200:0> a.delete_elements_in(b)
=> [1, 2, 4]
irb(main):201:0> a
=> [1, 2, 3, 3, 5]

Kod, iki dizi sıralanmadığında bile çalışır. Örnekte diziler sıralanmıştır, ancak bu gerekli değildir.


delete_elements_inRuby'de mevcut değil (ruby 2.6.3p62)
qaisjp

@qaisjp, çünkü yazar tarafından tanımlanmıştır. Sen de tanımlayacaksın. Test kodunun üstündeki koda bakın.
ismailarilik
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.