2012-07-05 13 views
6
class CartesianProduct 
include Enumerable 
# your code here 
end 
#Examples of use 
c = CartesianProduct.new([:a,:b], [4,5]) 
c.each { |elt| puts elt.inspect } 
# [:a, 4] 
# [:a, 5] 
# [:b, 4] 
# [:b, 5] 
c = CartesianProduct.new([:a,:b], []) 
c.each { |elt| puts elt.inspect } 
# (nothing printed since Cartesian product 
# of anything with an empty collection is empty) 

Ben ruby ​​için yeniyim. Kartezyen Ürünün bir örnek yöntemini nasıl tanımlayacağımı anlıyorum, ama bunun hakkında hiçbir fikrim yok. İhtiyacı yerine getirmek için sınıf nesnesini nasıl inşa etmeliyim.Kartezyen Ürün Ruby

+0

Lütfen ne için sorduğunuzu açıklayabilir misiniz? Neyi nasıl inşa etmelisin? Gösterilen şeyi yapacak 'CartesianProduct' adında bir sınıf oluşturmaya mı çalışıyorsunuz? – denniss

+0

Evet, bir sınıf yöntemi gerektirir. Bir değer döndürmek için bir örnek yöntemini nasıl yapılandıracağımı biliyorum, ancak sınıf nesnesinin değerini değiştirmek için sınıf yöntemini nasıl yapılandıracağımı bilmiyorum. – ZhijieWang

+0

Bu ev ödevi mi? Eğer öyleyse, sorun değil, insanlar sizi doğru yönde dürtmeye çalışacak. – steenslag

cevap

6

, ben yazmak istiyorum:

class CartesianProduct 
    include Enumerable 

    def initialize(xs, ys) 
    @xs = xs 
    @ys = ys 
    end 

    def each 
    return to_enum unless block_given? 
    @xs.each do |x| 
     @ys.each { |y| yield [x, y] } 
    end 
    end 
end 

Bunun yerine, basitçe xs.product(ys) yazmak veya inşa ediyorum benim kendi Array#lazy_product tembellik olsaydı önemli (bkz. bu ticket).

+0

Tembel kullanmaya gerek yok, değil mi? 'Her' ve bir verim daha basit ve daha hızlı olacak –

+0

Tamam, haklıydınız, dürüst olmak gerekirse tembel sürümü tercih ettim, bu daha işlevsel bir yaklaşım (ve standart olmayan bir blok kullanıldığında bir numaralayıcı döndürdü) 'each'). – tokland

+0

Gerçekten de, block_given olmadıkça tipik "return to_enum" ile başlamalısınız? –

22

Array#product'u kullanmanızı öneririz.

[:a, :b].product [4,5] 

İstediğiniz çıktıyı verecektir.

irb(main):001:0> [:a, :b].product [4,5] 
=> [[:a, 4], [:a, 5], [:b, 4], [:b, 5]] 
irb(main):002:0> 

Eğer tembel bir permütasyon jeneratörü istiyorsanız, daha önce böyle bir şey yazdım. Ama sizi uyarıyorum, hesaplamak için çok sayıda permütasyonunuz varsa, bir süre alabilir. İhtiyacınız olanı ilk 40 - 45 satırından this file'dan alabilmeniz gerekir (bu dosya zaten bir deneme idi).

Numara, dizileri bir dizi boyunca çalışmak için Ruby 1.9.2 kullanarak numaralandırıcılar oluşturmaktır. Böylece, bir dizide sonsuz bir şekilde döngü yapacak bir numaralayıcı oluşturursunuz ve dizi dizisi numaralandırıcınızda ilk çıkış kümesini izler ve ikinci kez vurulduğunda döngüyü sonlandırırsınız. Böyle bir döngüyü nasıl sonlandıracağımı anlayabilmemin tek yolu buydu.

def infinite_iterator(array) 
    Enumerator.new do |result| 
    loop do 
     array.cycle { |item| result << item } 
    end 
    end 
end 

def cartesian_iterator(data) 
    Enumerator.new do |result| 
    first = data.map { |p| p.next } 
    result << first 

    i = 1 
    parts = first.dup 
    loop do 
     parts[2-i] = data[2-i].next 
     break if parts == first 

     result << parts.join 
     i = ((i + 1) % parts.size) 
    end 
    end 
end 

array = [ infinite_iterator([:a,:b]), infinite_iterator([4,5]) ] 
generator = cartesian_iterator(array) 

generator.each { |a| p a } 
+0

İki boş diziden ne haber? Sonuç ne olacak? – ZhijieWang

+1

@ user1505108 Daha önce IRB'yi denediniz mi? Sonuç, [] 'dir. –

6

Sen ürünün her kombinasyon için yield çağırır sınıfınızda bir each yöntemi tanımlamak gerekir.

Array#product kullanabilirsiniz, ancak bir dizi döndürür, bu nedenle tembel değildir.

Sadece Ruby 2.0'da bir proposal for Array.product var.

Bunun için bir sınıf kullanın, ancak sorunun yapısını tutmak olmaz
+0

Teşekkür ederim, bu problemi çözüyor – ZhijieWang

+0

@ user1505108 Sonra bu cevabı işaretlemelisiniz (v-işareti). – steenslag

İlgili konular