2010-03-16 15 views
12

मैं पर्ल में क्रमपरिवर्तन करना चाहता हूं। उदाहरण के लिए मेरे पास तीन सरणी हैं: ["big", "tiny", "small"] और फिर मेरे पास ["red", "yellow", "green"] और ["apple", "pear", "banana"] भी है।पर्ल में, मैं कई सेटों के कार्टेशियन उत्पाद को कैसे प्राप्त कर सकता हूं?

मैं कैसे मिलता है:

["big", "red", "apple"] 
["big", "red", "pear"] 

..etc.. 

["small", "green", "banana"]

मैं समझता हूँ कि इस परिवर्तन कहा जाता है। लेकिन मुझे यकीन नहीं है कि यह कैसे करें। इसके अलावा मुझे नहीं पता कि मेरे पास कितने सरणी हो सकते हैं। तीन या चार हो सकते हैं, इसलिए मैं नेस्टेड लूप नहीं करना चाहता हूं।

+0

यह परिवर्तन नहीं है - क्रमचय एक सेट की orderings है (उदाहरण के लिए {ए, बी, सी} -> (ए, बी, सी), (ए, सी, बी), (बी, ए, सी), ...)। – Cascabel

+0

ओह क्षमा करें। मुझे नहीं पता था। क्या यह संयोजन है ?? – user295033

+0

वास्तव में, मैं सिर्फ देखा यह डुप्लिकेट है: देखो http://stackoverflow.com/questions/1256036/in-perl-how-can-i-iterate-over-the-cartesian-product-of-multiple-sets –

उत्तर

14

यह वास्तव में क्रमपरिवर्तन नहीं है लेकिन Cartesian product है। Math::Cartesian::Product देखें।

#!/usr/bin/perl 

use strict; use warnings; 

use Math::Cartesian::Product; 

cartesian { print "@_\n" } 
    ["big", "tiny", "small"], 
    ["red", "yellow", "green"], 
    ["apple", "pear", "banana"]; 

आउटपुट:

C:\Temp> uu 
big red apple 
big red pear 
big red banana 
big yellow apple 
big yellow pear 
big yellow banana 
big green apple 
big green pear 
big green banana 
tiny red apple 
tiny red pear 
tiny red banana 
tiny yellow apple 
tiny yellow pear 
tiny yellow banana 
tiny green apple 
tiny green pear 
tiny green banana 
small red apple 
small red pear 
small red banana 
small yellow apple 
small yellow pear 
small yellow banana 
small green apple 
small green pear 
small green banana
+0

ओह माय। मुझे पता नहीं था। इससे मुझे सिरदर्द का बहुत बचाया होगा! –

+0

धन्यवाद !!!! इसने मेरी बहुत मदद की। – user295033

+3

बस एक छोटा सा नोट: मठ :: कार्टेशियन :: उत्पाद आपको तुरंत पूरी जगह पर चलता है। वह हो सकता है जो आप चाहते हैं। यदि आप नियंत्रण उलटा करना चाहते हैं, तो सेट :: क्रॉस प्रोडक्ट का उपयोग करें। –

6

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

#!/usr/bin/perl 

print "permute:\n"; 
print "[", join(", ", @$_), "]\n" for permute([1,2,3], [4,5,6], [7,8,9]); 

sub permute { 

    my $last = pop @_; 

    unless(@_) { 
      return map([$_], @$last); 
    } 

    return map { 
       my $left = $_; 
       map([@$left, $_], @$last) 
       } 
       permute(@_); 
} 

हाँ, यह पागल है, लेकिन मुझे अनुमति देते हैं समझाना! समारोह @_ खाली होने तक रिकर्स करेगा, जिस बिंदु पर यह ([1], [2], [3]) (तीन सरणी की एक सूची) को रिकर्सन के पिछले स्तर पर लौटाता है। उस स्तर पर $last एक सरणी का संदर्भ है जिसमें [4, 5, 6] है।

बाहरी नक्शे के शरीर तो [1], तो [2] और अंत में [3] करने के लिए $_ सेट के साथ तीन बार चलाया जाता है। आंतरिक मानचित्र को बाहरी मानचित्र के प्रत्येक पुनरावृत्ति के लिए (4, 5, 6) पर चलाया जाता है और यह ([1, 4], [1, 5], [1, 6]), ([2, 4], [2, 5], [2, 6]), और अंत में ([3, 4], [3, 5], [3, 6]) देता है।

अंतिम लेकिन एक रिकर्सिव कॉल तब ([1, 4], [1, 5], [1, 6], [2, 4], [2, 5], [2, 6], [3, 4], [3, 5], [3, 6]) देता है।

फिर, यह [7,8,9] के खिलाफ है कि परिणाम है, जो आप [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]

मैं किसी ने मुझे यह समझाने के लिए पूछ perlmonks.org पर कोई प्रश्न पोस्ट याद देता है चलाता है।

आप आसानी से इस समस्या को अपनी समस्या में अनुकूलित कर सकते हैं।

+0

आपके समाधान के लिए धन्यवाद लेकिन मुझे लगता है कि सिनन का समाधान आसान है। लेकिन आपके समाधान को समझाने के लिए धन्यवाद – user295033

+0

कोई चिंता नहीं! मुझे सिनन का समाधान भी पसंद है। बहुत कम जटिल! –

5
अब

चहचहाना-रूप में:

sub prod { reduce { [ map { my $i = $_; map [ @$_, $i ], @$a } @$b ] } [[]], @_ }

use strict; 
use warnings; 
use List::Util qw(reduce); 

sub cartesian_product { 
    reduce { 
    [ map { 
     my $item = $_; 
     map [ @$_, $item ], @$a 
    } @$b ] 
    } [[]], @_ 
} 
+0

क्या आप समझा सकते हैं? यह अच्छा लग रहा है! – user295033

+1

@ nubie2 मूल रूप से यह है कि Vivin Paliath, केवल का उपयोग कर एक प्रत्यावर्तन के बजाय कम हो समाधान के रूप में ही है। एक 0-टुपल ('[[]]') की सूची से शुरू करें, और उसके बाद इनपुट में प्रत्येक सरणी के लिए, प्रत्येक आइटम को प्रत्येक मौजूदा प्रविष्टियों में संलग्न करें। यदि आप जानते हैं कि 'कम करें' क्या करता है, तो पेपर पर पता लगाने में काफी आसान है। यदि आपको नहीं पता कि 'कमी' क्या करता है, तो सीखें! :) – hobbs

+0

's/समाधान है कि स्पष्टीकरण के लिए /' – hobbs

6

यदि आप चाहें तो मेरे Set::CrossProduct मॉड्यूल का उपयोग कर सकते हैं। आपको पूरी जगह को पार करने की आवश्यकता नहीं है क्योंकि यह आपको एक इटेटरेटर देता है, इसलिए आप नियंत्रण में हैं।

0

यदि

  • आप

तो निर्भरता

  • आप सरणियों की एक छोटी संख्या है
  • अपने सरणियों वास्तव में बहुत बड़ा नहीं हैं शामिल करने के लिए नहीं करना चाहती आप बस ऐसा कर सकते हैं:

    दो सरणियों @xs और @ys के लिए:

    map{ my $x = $_; map { [$x, $_] } @ys } @xs 
    

    तीन सरणियों @xs, @ys के लिए, @zs

    map{ my $x = $_; map { my $y = $_; map { [$x, $y, $_] } @zs } @ys } @xs 
    
  • संबंधित मुद्दे