2017-05-02 10 views
5

मैं क्या करना चाहता हूं n सेट के साथ सौदा है, जबकि नीचे दिया गया कोड बिल्कुल 4 सेट के साथ काम करता है।आकार वाई की सरणी को देखते हुए, आकार एन के सरणी युक्त, मैं रूबी का उपयोग करके सभी तार्किक संयोजन कैसे वापस कर सकता हूं?

def show_combinations 
    @combos = [] 
    ['A', 'no A'].each do |a| 
    ['B', 'no B'].each do |b| 
     ['C', 'no C'].each do |c| 
     ['D', 'no D'].each do |d| 
      @combos << [a, b, c, d] 
     end 
     end 
    end 
    end 
end 

मैं कैसे इस परिदृश्य से निपटने के लिए इस निम्नलिखित कोड refactor कर सकते हैं: को देखते हुए मैं आकार आकार n के एरे युक्त y की एक सरणी है, मैं सभी संयोजनों वापस जाने के लिए चाहते हैं। यह ध्यान रखना महत्वपूर्ण है कि प्रत्येक उप सरणी में केवल एक आइटम परिणाम में हो सकता है। (जैसे "पूर्ण प्रोफाइल" भी "नहीं पूरा प्रोफ़ाइल" के साथ परिणाम में नहीं कर सकते हैं)

पृष्ठभूमि:

एक उपयोगकर्ता कुछ कार्य हो सकता है: उदाहरण के लिए, "पूरा प्रोफ़ाइल" या "के लिए सेट अप ईमेल "या जो भी हो। उन कार्यों को इस तरह दर्शाया जा सकता है:

@task_states = [["Completed Profile, NOT Completed Profile"], ["Set up Email", "NOT set up Email"]] 

फिर, विधि में @task_states गुजर, परिणाम यह होना चाहिए:

[ 
["Completed Profile", "Set up Email"], 
["Completed Profile", "NOT set up Email"], 
["NOT Completed Profile", "Set up Email"], 
["NOT Completed Profile", "NOT Set up Email"] 
] 

तो सभी संयोजनों का प्रतिनिधित्व सरणियों की एक सरणी। स्पष्ट रूप से "पूर्ण प्रोफ़ाइल" एक ही सरणी में "पूर्ण प्रोफ़ाइल नहीं," आदि के रूप में भी नहीं हो सकता है।

धन्यवाद!

+1

[ऐरे # संयोजन] (http://ruby-doc.org/core-2.4.1/Array.html#method-i-combination) या [ऐरे # repeated_combination] (http: // ruby-doc। संगठन/कोर-2.4.1/Array.html # विधि-i-repeated_combination) कोई अच्छा है? –

+1

क्या आपका मतलब एरे के कार्टेशियन उत्पाद है? –

उत्तर

9

ऐसा लगता है कि आप सरणी के कार्टशियन उत्पाद की गणना करना चाहते हैं। विधि है जिसके कार्तीय उत्पाद की गणना करता है (नहीं भी आश्चर्यजनक रूप से) Array#product कहा जाता है:

@task_states.first.product(*@task_states.drop(1)) 

तो, उदाहरण के लिए:

['A', 'no A'].product(['B', 'no B'], ['C', 'no C'], ['D', 'no D']) 
#=> [[ "A", "B", "C", "D"], 
# [ "A", "B", "C", "no D"], 
# [ "A", "B", "no C", "D"], 
# [ "A", "B", "no C", "no D"], 
# [ "A", "no B", "C", "D"], 
# [ "A", "no B", "C", "no D"], 
# [ "A", "no B", "no C", "D"], 
# [ "A", "no B", "no C", "no D"], 
# ["no A", "B", "C", "D"], 
# ["no A", "B", "C", "no D"], 
# ["no A", "B", "no C", "D"], 
# ["no A", "B", "no C", "no D"], 
# ["no A", "no B", "C", "D"], 
# ["no A", "no B", "C", "no D"], 
# ["no A", "no B", "no C", "D"], 
# ["no A", "no B", "no C", "no D"]] 
1

हर तरह से, Array#product उपयोग करें, लेकिन बार बार रूबी के साथ मामले में , अन्य तरीके हैं। यहां दो हैं।

arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

उपयोग गणित arr.size**arr.first.size संयोजन

def cartesian_product(arr) 
    n, m = arr.size, arr.first.size 
    (0..n**m-1).map do |x| 
    (n-1).downto(0).map do |i| 
     x, r = x.divmod(m) 
     arr[i][r] 
    end.reverse 
    end 
end 

cartesian_product arr 
    #=> [[1, 4, 7], [1, 4, 8], [1, 4, 9], [1, 5, 7], [1, 5, 8], [1, 5, 9], 
    # [1, 6, 7], [1, 6, 8], [1, 6, 9], 
    # [2, 4, 7], [2, 4, 8], [2, 4, 9], [2, 5, 7], [2, 5, 8], [2, 5, 9], 
    # [2, 6, 7], [2, 6, 8], [2, 6, 9], 
    # [3, 4, 7], [3, 4, 8], [3, 4, 9], [3, 5, 7], [3, 5, 8], [3, 5, 9], 
    # [3, 6, 7], [3, 6, 8], [3, 6, 9]] 

प्रत्यावर्तन उपयोग

def cartesian_product(arr) 
    first, *rest = arr 
    return first.map { |o| [o] } if rest.empty? 
    c = cartesian_product(rest) 
    first.flat_map { |o| c.map { |a| [o] + a } } 
end 

cartesian_product arr 
    #=> same as above 

इस आवेदन arr के प्रत्येक तत्व (सरणी) कोई डुप्लिकेट शामिल में से प्रत्येक गणना करने के लिए। अन्य स्थितियों में, जहां डुप्लिकेट मौजूद हो सकता है (और जहां लौटे उत्पादों डुप्लिकेट को रोकने के लिए नहीं कर रहे हैं), एक पहले की गणना करना चाहिए

arr_without_dups = arr.map(&:uniq) 

और फिर arr_without_dups से संयोजन की गणना।

1

जबकि दिए गए उत्तरों बहुत अच्छे थे और जोर्ग मैं स्वीकार करता हूं, मैं जवाब साझा करना चाहता था कि मेरे किसी एक मित्र ने मुझे इस प्रश्न का सामना करने के मामले में प्रदान किया। अनिवार्य रूप से यह जोर्ग का जवाब है लेकिन थोड़ी अधिक गहराई के साथ।

कार्तीय उत्पादों आप के लिए Cartesian Product कहा जाता है क्या कह रहे हैं और यह पहले से ही Array#product साथ में बनाया गया है।

उदाहरण के लिए:

[0, 1].product([0, 1]) 
# => [[0, 0], [0, 1], [1, 0], [1, 1]] 

सूचना है कि इस हमें हर संभव 2-बिट नंबर देता है, से 00-11

आप सरणी # उत्पाद सरणियों के किसी भी संख्या दे सकते हैं:

[0, 1].product([0, 1], [0, 1]) 
# => [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]] 

ध्यान दें कि यह हमें 000-111 से सभी संभावित 3-बिट संख्या देता है।

आपकी समस्या अपने सटीक समस्या को देखते हुए:

["A", "no A"].product(["B", "no B"], ["C", "no C"], ["D", "no D"]) 
=> [["A", "B", "C", "D"], 
["A", "B", "C", "no D"], 
["A", "B", "no C", "D"], 
["A", "B", "no C", "no D"], 
["A", "no B", "C", "D"], 
["A", "no B", "C", "no D"], 
["A", "no B", "no C", "D"], 
["A", "no B", "no C", "no D"], 
["no A", "B", "C", "D"], 
["no A", "B", "C", "no D"], 
["no A", "B", "no C", "D"], 
["no A", "B", "no C", "no D"], 
["no A", "no B", "C", "D"], 
["no A", "no B", "C", "no D"], 
["no A", "no B", "no C", "D"], 
["no A", "no B", "no C", "no D"]] 
gives you all the possible combinations from "ABCD" to "noA noB noC noD" 

जेनेरिक समाधान हम सूचक * ऑपरेटर का लाभ उठाकर सरणियों के किसी भी सामान्य सरणी के साथ इस काम कर सकते हैं।

def combinations(arrays) 
    first, *rest = arrays 
    first.product(*rest) 
end 

तो हम कह सकते हैं: मुझे इस के साथ मदद करने के साथ ही लोग हैं, जो जवाब प्रदान की से बाकी के लिए

arrays_to_combine = [["A", "no A"], ["B", "no B"], ["C", "no C"], ["D", "no D"]] 
combinations(arrays_to_combine) 
=> [["A", "B", "C", "D"], 
["A", "B", "C", "no D"], 
["A", "B", "no C", "D"], 
["A", "B", "no C", "no D"], 
["A", "no B", "C", "D"], 
["A", "no B", "C", "no D"], 
["A", "no B", "no C", "D"], 
["A", "no B", "no C", "no D"], 
["no A", "B", "C", "D"], 
["no A", "B", "C", "no D"], 
["no A", "B", "no C", "D"], 
["no A", "B", "no C", "no D"], 
["no A", "no B", "C", "D"], 
["no A", "no B", "C", "no D"], 
["no A", "no B", "no C", "D"], 
["no A", "no B", "no C", "no D"]] 

Thoughtbot के जोएल क्वेनेविल को विशेष धन्यवाद।

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