2012-07-05 9 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) 

मैं रूबी के लिए नया हूं। और मैं समझता हूं कि कार्टेसियन उत्पाद की एक उदाहरण विधि को कैसे परिभाषित किया जाए, लेकिन मुझे इसका कोई संकेत नहीं है। आवश्यकता को पूरा करने के लिए मुझे कक्षा वस्तु का निर्माण कैसे करना चाहिए।कार्टेशियन उत्पाद रूबी

+0

क्या आप कृपया बता सकते हैं कि आप क्या पूछ रहे हैं? आपको कैसे बनाना चाहिए? क्या आप 'कार्टेशियन प्रोडक्ट' नामक एक कक्षा बनाने की कोशिश कर रहे हैं जो दिखाएगा क्या करेगा? – denniss

+0

हां, इसके लिए एक क्लास विधि की आवश्यकता है। मुझे पता है कि एक मूल्य वापस करने के लिए एक उदाहरण विधि कैसे बनाएं, लेकिन मुझे नहीं पता कि क्लास ऑब्जेक्ट के मान को संशोधित करने के लिए क्लास विधि कैसे बनाएं। – ZhijieWang

+0

क्या यह होमवर्क है? यदि ऐसा है, तो यह ठीक है, लोग आपको सही दिशा में घुमाने की कोशिश करेंगे। उत्पाद की लंबाई – steenslag

उत्तर

6

मुझे लगता है कि के लिए एक वर्ग का उपयोग नहीं होगा, लेकिन सवाल की संरचना रखते हुए, मैं लिखने चाहते हैं:

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 

इसके बजाय, मैं बस xs.product(ys) लिख सकते हैं या निर्माण होता मेरे अपने Array#lazy_product अगर आलस्य थे महत्वपूर्ण (यह ticket देखें)।

+0

आलसी का उपयोग करने की कोई आवश्यकता नहीं है, हालांकि, वहां है? सीधे 'प्रत्येक' और 'उपज' सीधे –

+0

ठीक होगा, ठीक है, हालांकि मैं ईमानदार होने के लिए आलसी संस्करण पसंद करता हूं, यह एक अधिक कार्यात्मक दृष्टिकोण है (और मानक के समान ब्लॉक के बिना उपयोग किए जाने पर एक गणनाकर्ता लौटाता है 'each')। – tokland

+0

दरअसल, आपको संभवतः सामान्य 'वापसी to_enum से शुरू करना चाहिए जब तक कि ब्लॉक_गुवेन न हो?' –

22

मैं Array#product का उपयोग करने का सुझाव देता हूं।

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

जो आपके इच्छित आउटपुट को उत्पन्न करेगा।

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

यदि आप क्रमपरिवर्तन के आलसी जनरेटर चाहते हैं, तो मैंने पहले ऐसा कुछ लिखा है। लेकिन मैं आपको चेतावनी देता हूं, अगर आपके पास गणना करने के लिए बड़ी संख्या में क्रमपरिवर्तन हैं तो इसमें कुछ समय लग सकता है। आपको this file की पहली 40 - 45 लाइनों से जो चाहिए उसे लेने में सक्षम होना चाहिए (यह फ़ाइल वैसे भी एक प्रयोग थी)।

यह चाल रूबी 1.9.2 का उपयोग करके एनीमेशन की एक सरणी के माध्यम से अपना रास्ता बनाने के लिए गणना करने के लिए है। तो आप पहले एक गणनाकर्ता बनाते हैं जो अंतहीन रूप से किसी सरणी के माध्यम से चक्र चलाएगा, और आपके सरणी-ऑफ-एरे एन्यूमरेटर में आप पहले आउटपुट सेट को ट्रैक करेंगे और दूसरी बार हिट होने पर लूप को समाप्त करेंगे। यह एकमात्र तरीका था जिसे मैं समझ सकता हूं कि इस तरह के लूप को कैसे समाप्त किया जाए।

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

दो खाली सरणी के बारे में क्या? परिणाम क्या होगा? – ZhijieWang

+1

@ user1505108 क्या आपने पहले आईआरबी की कोशिश की है? परिणाम '[]' है। –

6

आप अपने वर्ग है कि उत्पाद के प्रत्येक संयोजन के लिए yield कॉल में एक each विधि को परिभाषित करने की जरूरत है।

आप Array#product का उपयोग कर सकते हैं, लेकिन यह एक सरणी देता है, इसलिए यह आलसी नहीं है।

रुबी 2.0 में proposal for Array.product है जो बस ऐसा करेगा।

+0

धन्यवाद, जो समस्या को हल करता है – ZhijieWang

+0

@ user1505108 तो आपको यह उत्तर (v-sign) चिह्नित करना चाहिए। – steenslag

संबंधित मुद्दे