दिलचस्प पोस्ट
पॉपवर को कब तक रखा जा रहा है, मैं कैसे बूटस्ट्रैप पॉपवर को जीवित रख सकता हूं? जावा 32-बिट बनाम 64-बिट संगतता मैं एक बाइट डालें कैसे एक एसक्यूएल सर्वर VARBINARY कॉलम में सीएसएस में सेलपैडिंग और सेलेक्शनिंग सेट करें? java.lang.UnsupportedClassVersionError: .class फ़ाइल में खराब संस्करण संख्या? क्या NuGet के लिए संकुल के स्थान को बदलना संभव है? कैसे <div> टैग को <code> / <pre> टैग में शाब्दिक दिखाना है? ओरेकल डाटाबेस में सी # से कनेक्ट करने के लिए आवश्यक न्यूनतम ग्राहक पदचिह्न क्या है? जावा जीयूआई चौखटे क्या चुनना है? स्विंग, SWT, एडब्ल्यूटी, स्विंगएक्स, जेगूडिज़, जावा एफएक्स, अपाचे पिवट? WPF में, एक्स: नाम और नाम के गुणों के बीच अंतर क्या हैं? कैसे पूरे regex नकारना? सी / सी ++ बहुआयामी सरणी इंटरनेशनल MySQL में पदानुक्रमित क्वेरी विंडोज फॉर्म में किसी अन्य फॉर्म पर नियंत्रण का उपयोग करने का सर्वोत्तम तरीका है? मैं 2 विभिन्न y- अक्षों के साथ कैसे साजिश कर सकता हूं?

PHP एसोसिएटिव सरणियों के साथ कार्टेशियन उत्पाद ढूँढना

कहें कि मेरे पास निम्न की तरह एक सरणी है:

Array ( [arm] => Array ( [0] => A [1] => B [2] => C ) [gender] => Array ( [0] => Female [1] => Male ) [location] => Array ( [0] => Vancouver [1] => Calgary ) ) 

बाहरी सहायक अरै की चाबियों को संरक्षित करते हुए और आंतरिक लोगों में उनका उपयोग करते समय मैं कार्टेशियन उत्पाद कैसे पा सकता हूं? एल्गोरिथ्म का नतीजा यह होना चाहिए:

 Array ( [0] => Array ( [arm] => A [gender] => Female [location] => Vancouver ) [1] => Array ( [arm] => A [gender] => Female [location] => Calgary ) [2] => Array ( [arm] => A [gender] => Male [location] => Vancouver ) ...etc. 

मैंने बहुत से कार्टेसियन उत्पाद एल्गोरिदम को देखा है लेकिन मैं संयोजी कुंजियों को कैसे संरक्षित करने की बारीकियों पर फंस गया हूं मैं उपयोग कर रहा हूँ वर्तमान एल्गोरिदम केवल संख्यात्मक सूचकांक देता है:

  $result = array(); foreach ($map as $a) { if (empty($result)) { $result = $a; continue; } $res = array(); foreach ($result as $r) { foreach ($a as $v) { $res[] = array_merge((array)$r, (array)$v); } } $result = $res; } print_r($result); 

किसी भी सहायता की सराहना की जाएगी।

वेब के समाधान से एकत्रित समाधान "PHP एसोसिएटिव सरणियों के साथ कार्टेशियन उत्पाद ढूँढना"

यह एक ऐसा समाधान है जिसे मैं शो में नहीं दिखाऊंगा।

दलील

मान लें कि हमारे N -सब-एरेज़ के साथ हमारे पास इनपुट सरणी $input , जैसा आपके उदाहरण में है। प्रत्येक उप-सरणी में Cn वस्तुएं होती हैं, जहां n इसकी $input IN $input IN $input , और इसकी कुंजी है Kn । मैं वें उप-सरणी के i वें मद को संदर्भित करेगा जो Vn,i

नीचे दिए गए एल्गोरिदम को प्रेरित करने के लिए (बग्स को छोड़कर) काम करने के लिए साबित किया जा सकता है:

1) एन = 1 के लिए, कार्टेसीयन उत्पाद array(0 => array(K1 => V1,1), 1 => array(K1 => V1,2), ... ) – कुल में सी 1 आइटम । यह एक सरल foreach साथ किया जा सकता है

2) मान लें कि $result पहले से पहले एन -1 उप-एरे के कार्टेसियन उत्पाद रखता है। $result का कार्टेशियन उत्पाद और एनथ उप-सरणी इस तरह से बनाया जा सकता है:

3) प्रत्येक आइटम (सरणी) में $product अंदर, मूल्य KN => VN,1 परिणामस्वरूप वस्तु याद रखें (जोड़ा मूल्य के साथ); मैं इसे $item रूप में संदर्भित करूंगा

4 ए) $product सरणी के भीतर प्रत्येक सरणी के लिए:

4 बी) सेट VN,2 ... VN,CN में प्रत्येक मान के लिए VN,2 ... VN,CN $product एक कॉपी $item , लेकिन कुंजी KN के साथ VN,m (सभी 2 <= m <= CN लिए मान बदलें )।

दो पुनरावृत्त 4 ए ( $product से अधिक) और 4 बी (एनआईपी इनपुट उप-एरे से अधिक) को $result साथ समाप्त होता है जिसमें प्रत्येक आइटम के पुनरावृत्त होने से पहले CN वस्तु होती है, इसलिए अंत में $result वास्तव में कार्टेसियन उत्पाद शामिल है पहले एन उप एरेज़

इसलिए एल्गोरिथ्म किसी भी एन के लिए काम करेगा

यह होना चाहिए था की तुलना में यह लिखना कठिन था। मेरे औपचारिक प्रमाण निश्चित रूप से जंगली हो रहे हैं …

कोड

 function cartesian($input) { $result = array(); while (list($key, $values) = each($input)) { // If a sub-array is empty, it doesn't affect the cartesian product if (empty($values)) { continue; } // Seeding the product array with the values from the first sub-array if (empty($result)) { foreach($values as $value) { $result[] = array($key => $value); } } else { // Second and subsequent input sub-arrays work like this: // 1. In each existing array inside $product, add an item with // key == $key and value == first item in input sub-array // 2. Then, for each remaining item in current input sub-array, // add a copy of each existing array inside $product with // key == $key and value == first item of input sub-array // Store all items to be added to $product here; adding them // inside the foreach will result in an infinite loop $append = array(); foreach($result as &$product) { // Do step 1 above. array_shift is not the most efficient, but // it allows us to iterate over the rest of the items with a // simple foreach, making the code short and easy to read. $product[$key] = array_shift($values); // $product is by reference (that's why the key we added above // will appear in the end result), so make a copy of it here $copy = $product; // Do step 2 above. foreach($values as $item) { $copy[$key] = $item; $append[] = $copy; } // Undo the side effecst of array_shift array_unshift($values, $product[$key]); } // Out of the foreach, we can add to $results now $result = array_merge($result, $append); } } return $result; } 

प्रयोग

 $input = array( 'arm' => array('A', 'B', 'C'), 'gender' => array('Female', 'Male'), 'location' => array('Vancouver', 'Calgary'), ); print_r(cartesian($input)); 

इसे कार्रवाई में देखें!

यहां @ जॉन के कार्टेशियन समारोह का अनुकूलित संस्करण है:

 function cartesian($input) { // filter out empty values $input = array_filter($input); $result = array(array()); foreach ($input as $key => $values) { $append = array(); foreach($result as $product) { foreach($values as $item) { $product[$key] = $item; $append[] = $product; } } $result = $append; } return $result; } 

और यहां इस एल्गोरिदम के पीछे गणित है: http://en.wikipedia.org/wiki/Cartesian_product

यहां बताया गया है कि मैं क्या कर सकता हूं:

 function inject($elem, $array) { return array_map(function ($n) use ($elem) { return array_merge((array)$elem, (array)$n); }, $array); } function zip($array1, $array2) { return array_reduce($array1, function ($v, $n) use ($array2) { return array_merge($v, inject($n, $array2)); }, array()); } function cartesian_product($array) { $keys = array_keys($array); $prod = array_shift($array); $prod = array_reduce($array, 'zip', $prod); return array_map(function ($n) use ($keys) { return array_combine($keys, $n); }, $prod); } 

(नीचे छद्म सरणी / सूची / शब्दकोश नोटेशन का उपयोग करना क्योंकि PHP ऐसी चीज़ों के लिए बहुत ही ज़रूरी है।)

inject फंक्शन a, [b] में [(a,b)] बदलता a, [b] यानी यह एक सरणी के प्रत्येक मान में एक सिंगल मान को इंजेक्ट करता है, सरणी की एक सरणी लौटाता है। इससे कोई फर्क नहीं पड़ता कि क्या a या b पहले से ही एक सरणी है, यह हमेशा एक दो आयामी सरणी वापस कर देगा।

 inject('a', ['foo', 'bar']) => [('a', 'foo'), ('b', 'bar')] 

सरणी में प्रत्येक तत्व को zip फ़ंक्शन inject फ़ंक्शन लागू करता है।

 zip(['a', 'b'], ['foo', 'bar']) => [('a', 'foo'), ('a', 'bar'), ('b', 'foo'), ('b', 'bar')] 

ध्यान दें कि यह वास्तव में कार्टेसीयन उत्पाद का उत्पादन करता है, इसलिए zip एक मामूली मिथ्या नाम है बस इस समारोह को उत्तराधिकार में सेट किए गए डेटा सेट के सभी तत्वों पर लागू करने से आपको किसी भी लम्बाई के सरणी के लिए कार्टेसीयन उत्पाद मिलता है।

 zip(zip(['a', 'b'], ['foo', 'bar']), ['42', '76']) => [('a', 'foo', '42'), ('a', 'foo', '76'), ('a', 'bar', '42'), …] 

इसमें चाबियाँ शामिल नहीं हैं, लेकिन जब से परिणाम सभी सेट के भीतर क्रमबद्ध होते हैं, तो आप परिणाम में चाबियाँ बस फिर से कर सकते हैं।

 array_combine(['key1', 'key2', 'key3'], ['a', 'foo', '42']) => [ key1 : 'a', key2 : 'foo', key3 : '42' ] 

इस उत्पाद के सभी तत्वों को लागू करना वांछित परिणाम देता है।

यदि आप चाहें तो आप ऊपर दिए गए तीन फ़ंक्शंस को एक एकल बयान में मिटा सकते हैं (जो कि मिथकों को भी साफ़ कर देगा)


PHP के लिए अनाम कार्यों के बिना एक "अनारोल्ड" संस्करण <= 5.2 इसी तरह दिखाई देगा:

 function inject($elem, $array) { $elem = (array)$elem; foreach ($array as &$a) { $a = array_merge($elem, (array)$a); } return $array; } function zip($array1, $array2) { $prod = array(); foreach ($array1 as $a) { $prod = array_merge($prod, inject($a, $array2)); } return $prod; } function cartesian_product($array) { $keys = array_keys($array); $prod = array_shift($array); $prod = array_reduce($array, 'zip', $prod); foreach ($prod as &$a) { $a = array_combine($keys, $a); } return $prod; } 

क्यों एक पुनरावर्ती जनरेटर का उपयोग नहीं करें … स्मृति समस्याएं: कोई भी करीब नहीं
(और यह सुंदर है)

 function cartesian($a) { if ($a) { if($u=array_pop($a)) foreach(cartesian($a)as$p) foreach($u as$v) yield $p+[count($p)=>$v]; } else yield[]; } 

ध्यान दें: यह कुंजियों को संरक्षित नहीं करता है; लेकिन यह एक शुरुआत है

यह करना चाहिए (परीक्षण नहीं किया गया है):

 function acartesian($a) { if ($a) { $k=end(array_keys($a)); if($u=array_pop($a)) foreach(acartesian($a)as$p) foreach($u as$v) yield $p+[$k=>$v]; } else yield[]; } 

मैंने जल्दी से आपके कोड को थोड़ा समायोजित किया, मेरा प्रयास कच्चा है, लेकिन मुझे लगता है कि यह काम आप चाहते हैं या नहीं।

 $result = array(); $nm = ''; foreach ($map as $name => $a) { if (empty($result)) { $result = $a; $nm = $name; continue; } $res = array(); foreach ($result as $r) { foreach ($a as $v) { $myr = $r; $myv = $v; if(!is_array($r)) $myr = array($nm => $r); if(!is_array($v)) $myv = array($name => $v); $res[] = array_merge($myr, $myv); } } $result = $res; } echo "<pre>"; print_r($result); 

एक और समाधान:

 function getAllVariations($input) { $result = array(); $cnt = array_product(array_map('count', $input)); $step = 1; foreach ($input as $key=>$array) { for ($i=0; $i<$cnt; $i++) { foreach ($array as $value) { for ($k=0; $k<$step; $k++) { $result[$i+$k][$key] = $value; } $i += $step; } $i--; } $step = $step * count($array); } return $result; } 

उपयोग:

 $input = array( 'arm' => array('A', 'B', 'C'), 'gender' => array('Female', 'Male'), 'location' => array('Vancouver', 'Calgary'), 'name' => array('Rio', 'Mark') ); echo "<pre>"; var_dump(getAllVariations($input)); 

ऐसा करने के लिए डेटाबेस का उपयोग क्यों नहीं करें?

यह MySQL में आसान है ..

 table arm id integer primary key label char table gender id integer primary key gender enum('male','female') table location id integer primary key city varchar(255) 

फिर एक क्वेरी करें

 $query = mysql_query(" SELECT a.label, g.gender, l.city FROM arm a CROSS JOIN gender g CROSS JOIN location l ORDER BY a.id ") or die("Could not execute query"); while($row = mysql_fetch_array($query) ) { .... } 

और इसे पढ़ें:

यदि स्मृति की खपत महत्वपूर्ण है या आपको अंत में सभी संयोजनों की आवश्यकता नहीं है, तो आप एक बार में एक संयोजन बनाने के लिए इटरेटर का उपयोग कर सकते हैं। यदि आप सभी संयोजनों की आवश्यकता है तो आप iterator_to_array उपयोग कर सकते हैं।

 function cartezianIterator($inputArray) { $maximumPosition = array_map('count', $inputArray); $position = array_pad([], count($inputArray), 0); while (false !== ($item = buildItemAtPosition($inputArray, $position))) { yield $item; $position = incrementPosition($position, $maximumPosition); } } function buildItemAtPosition($inputArray, $positions) { if ($positions[0] >= count($inputArray[0])) { return false; } $item = []; foreach ($inputArray as $rowIndex => $row) { $position = $positions[$rowIndex]; $item[] = $row[$position]; } return $item; } function incrementPosition($position, $maximumPosition) { $digitToIncrement = count($position) - 1; do { $position[$digitToIncrement]++; if ($position[$digitToIncrement] < $maximumPosition[$digitToIncrement] || 0 === $digitToIncrement) { //no overflow break; } //overflow, reset to zero and increment parent digit $position[$digitToIncrement] = 0; $digitToIncrement--; } while ($digitToIncrement >= 0); return $position; } 

उसके बाद, एक समय में एक समाधान प्राप्त करने के लिए आप एक foreach या next उपयोग कर सकते हैं, इस तरह:

 $iterator = cartezianIterator($inputArray); //of course, you need to do something with the result... $combination = next($iterator); $combination = next($iterator); $combination = next($iterator); $combination = next($iterator); $combination = next($iterator); $combination = next($iterator); 

यदि आपको केवल कुछ संयोजनों की आवश्यकता होती है तो यह समाधान बहुत तेज है। इसके अलावा, स्मृति खपत बहुत कम है (यह कुछ integers को संग्रहीत करने के लिए एक फ्लैट array का उपयोग करता है)

नोट: पुनरावर्ती कार्यों का उपयोग नहीं किया जाता है।

एक एल्गोरिथ्म प्रत्येक चरण में मौजूदा चरण वस्तुओं के साथ पिछले परिणामों का विस्तार करना है:

 function cartezian1($inputArray) { $results = []; foreach ($inputArray as $group) { $results = expandItems($results, $group); } return $results; } function expandItems($sourceItems, $tails) { $result = []; if (empty($sourceItems)) { foreach ($tails as $tail) { $result[] = [$tail]; } return $result; } foreach ($sourceItems as $sourceItem) { foreach ($tails as $tail) { $result[] = array_merge($sourceItem, [$tail]); } } return $result; } 

यह समाधान सभी संयोजनों को संग्रहीत करने के लिए मेमोरी का उपयोग करता है, फिर उन सभी को एक बार में रिटर्न करता है। इसलिए, यह तेज़ है, लेकिन इसकी बहुत मेमोरी की आवश्यकता है इसके अलावा, पुनरावर्ती कार्यों का उपयोग नहीं किया जाता है।

सर्ज के उत्तर @ PHP 7 में कम किया जा सकता है:

 function cartesian(array $input) { $result = [[]]; foreach ($input as $key => $values) { $append = []; foreach ($values as $value) { foreach ($result as $data) { $append[] = $data + [$key => $value]; } } $result = $append; } return $result; }