2016-12-01 73 views
2

爲了優化輸出,我最近遇到了一種情況,我必須得到數組內所有數組鍵。我查看了幾個地方(包括StackOverflow),但找不到解決方案,因爲大多數地方都與排列相關而不是組合。查找數組鍵與值的組合

鑑於此輸入

$input = ['jack' => 11, 'moe' => 12, 'shane' => 12]; 

輸出應該是這樣的(一個陣列內的順序並不重要)。

$output = [  
    ['jack' => 11], 
    ['jack' => 11, 'moe' => 12] 
    ['jack' => 11, 'moe' => 12, 'shane' => 12] 
    ['moe' => 12], 
    ['moe' => 12, 'shane' => 12] 
    ['shane' => 12], 
    ['shane' => 12, 'jack' => 11] 
]; 

我試過這個,但經過第三次迭代後它不起作用。

function combination(array $inputs, array $temp, &$collect) { 

    if (!empty($temp)) { 

     $collect[] = $temp; 
    } 

    for ($i = 0; $i < sizeof($inputs); $i++) { 

     $inputCopy = $inputs; 

     $elem = array_splice($inputCopy, $i, 1); 

     if (count($inputCopy) > 0) { 

      $temp[array_keys($elem)[0]] = array_values($elem)[0]; 

      combination($inputCopy, $temp, $collect); 

     } else { 

      $temp[array_keys($elem)[0]] = array_values($elem)[0]; 
      $collect[] = $temp; 
      $temp = []; 
     } 

     $i++; 

    } 
} 

雖然我需要PHP甚至是Python甚至Python(不使用itertools組合),但Java,Javascript將適用於我。

回答

1

您在這裏閱讀了非常聰明的非遞歸算法:PHP: Find every combination of an Array。這裏

function keyCombinations($array) 
{ 
    $keys = array_keys($array); 

    $num = count($keys); 
    $total = pow(2, $num); 

    for ($i = 1; $i < $total; $i++) { 
     $combination = []; 
     for ($j = 0; $j < $num; $j++) { 
      if (pow(2, $j) & $i) { 
       $key = $keys[$j]; 

       $combination[$key] = $array[$key]; 
      } 
     } 
     yield $combination; 
    } 
} 

很重要的一點:你可以通過它(主要是複製和粘貼)寫generator function。在使用0初始化的原始文章$i中,我們用1對它初始化以從結果中排除空數組。

有了這個功能,你可以得到所有的組合:

foreach (keyCombinations($input) as $combination) { 
    print_r($combination); 
} 

這裏是working demo

+0

我不得不在你的例子中做一些改變,但它的工作。非常感謝你。 – nicholasnet

0

如果在最終組合中包含空集,那麼問題就等同於枚舉二進制數「n」位。其中「n」是你的集合中元素的數量。

你需要一個遞歸算法像這樣的:

def comb(initialSet, results=[], currentIndex=0, currentResult=[]): 
    if currentIndex >= len(initialSet): 
     results.append(currentResult[:]) 
    else: 
     currentResult.append(initialSet[currentIndex]) 
     comb(initialSet, results, currentIndex + 1, currentResult) 
     currentResult.pop() 
     comb(initialSet, results, currentIndex + 1, currentResult) 
    return results 
2

我發現做你想要什麼樣的一種方式,但肯定,這不是一個「神奇」的解決方案。我建議你用一點點工作來找到更好的東西,但至少這會給你結果。

在這裏你去:

<?php 

    $baseArray = [ 
    "joe" => 11, 
    "molly" => 12, 
    "sam" => 13, 
    ]; 

function getAllPermutations($array = []) { 
    if (empty($array)) { 
     return []; 
    } 

    $result = []; 

    foreach ($array as $key => $value) { 
     unset($array[$key]); 
     $subPermutations = getAllPermutations($array); 
     $result[] = [$key => $value]; 
     foreach ($subPermutations as $sub) { 
      $result[] = array_merge([$key => $value] , $sub); 
     } 
    } 
    return $result; 
} 

print_r(getAllPermutations($baseArray)); 

輸出中:

Array 
(
    [0] => Array 
     (
      [joe] => 11 
     ) 

    [1] => Array 
     (
      [joe] => 11 
      [molly] => 12 
     ) 

    [2] => Array 
     (
      [joe] => 11 
      [molly] => 12 
      [sam] => 13 
     ) 

    [3] => Array 
     (
      [joe] => 11 
      [sam] => 13 
     ) 

    [4] => Array 
     (
      [molly] => 12 
     ) 

    [5] => Array 
     (
      [molly] => 12 
      [sam] => 13 
     ) 

    [6] => Array 
     (
      [sam] => 13 
     ) 

) } 

希望這有助於。

+0

非常感謝您的回覆。但是這個解決方案並沒有像這樣的輸入。 '$ input = [123 => 0.3,124 => 0.3,125 => 0.6,126 => 0.9]; 在第二次迭代中,鍵都是。 – nicholasnet

+0

但它幫助我更好地理解了這個問題。非常感謝你。 – nicholasnet

+0

其實你的代碼中只有問題是 '$ result [] = array_merge([$ key => $ value],$ sub);'應該是'$ result [] = [$ key => $ value] + $ sub;' 休息很好,謝謝。 – nicholasnet