2016-12-01 72 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