PHP找到一个数组的所有(有点)唯一组合(PHP Find All (somewhat) Uniqu

2019-09-01 13:30发布

我一直在寻找PHP阵列排列/组合问题全天..和仍然无法弄清楚:/

如果我有一个数组,如:

20 //key being 0    
20 //key being 1    
22 //key being 2    
24 //key being 3

我需要一个像组合:

20, 20, 22 //keys being 0 1 2    
20, 20, 24 //keys being 0 1 3    
20, 22, 24 //keys being 0 2 3
20, 22, 24 //keys being 1 2 3

我现在有代码给我:

20, 22, 24

因为它不希望重复20 ......但是这就是我所需要的!

这里是我的代码。 它是直接从PHP的递归以获得字符串的所有可能性

function getCombinations($base,$n){

$baselen = count($base);
if($baselen == 0){
    return;
}
    if($n == 1){
        $return = array();
        foreach($base as $b){
            $return[] = array($b);
        }
        return $return;
    }else{
        //get one level lower combinations
        $oneLevelLower = getCombinations($base,$n-1);

        //for every one level lower combinations add one element to them that the last element of a combination is preceeded by the element which follows it in base array if there is none, does not add
        $newCombs = array();

        foreach($oneLevelLower as $oll){

            $lastEl = $oll[$n-2];
            $found = false;
            foreach($base as  $key => $b){
                if($b == $lastEl){
                    $found = true;
                    continue;
                    //last element found

                }
                if($found == true){
                        //add to combinations with last element
                        if($key < $baselen){

                            $tmp = $oll;
                            $newCombination = array_slice($tmp,0);
                            $newCombination[]=$b;
                            $newCombs[] = array_slice($newCombination,0);
                        }

                }
            }

        }

    }

    return $newCombs;


}

我一直在玩与周围的($b == $lastEl)线,没有运气

===============

问题我已经看了看,是不一样的或创建的内存不足的错误!:

  • 我怎样才能在PHP中所有的排列顺序不重复?
  • 置换-所有可能的两组数字
  • 组合,配置与在PHP排列组合
  • PHP阵列组合
  • 找一个PHP数组的所有排列?
  • PHP:如何得到一维数组的所有可能的组合?
  • 从这个数组只选择唯一的数组值
  • 找一个PHP数组的所有排列?
  • PHP:如何得到一维数组的所有可能的组合?
  • 从这个数组只选择唯一的数组值
  • 我怎样才能在PHP中所有的排列顺序不重复?
  • 算法来从n个返回k个元素的所有组合
  • 查找数组,其总和等于组合(一个或多个)元件(一个或多个)的总和到一个给定数目的
  • 组合,配置与在PHP排列组合
  • PHP阵列组合
  • PHP递归以获得字符串的所有可能性
  • 如何返回数组的排列在PHP?
  • 置换-所有可能的两组数字
  • 在PHP子集和问题与MySQL
  • 从阵列滤除任何重复的双值找到的独特组合
  • 查找字符串的所有唯一排列,而不会产生重复
  • 生成所有独特的排列
  • 子总和恰好有k个整数?

我已经尝试了一些这些算法有12个项目的阵列,并最终运行内存。 不过我目前使用的是不给我一个内存不足错误的算法....但..我需要这些重复的!

Answer 1:

如果你不介意使用一对全局变量,你可以在PHP(从翻译做这个版本在JavaScript):

<?PHP
$result = array(); 
$combination = array();

function combinations(array $myArray, $choose) {
  global $result, $combination;

  $n = count($myArray);

  function inner ($start, $choose_, $arr, $n) {
    global $result, $combination;

    if ($choose_ == 0) array_push($result,$combination);
    else for ($i = $start; $i <= $n - $choose_; ++$i) {
           array_push($combination, $arr[$i]);
           inner($i + 1, $choose_ - 1, $arr, $n);
           array_pop($combination);
         }
  }
  inner(0, $choose, $myArray, $n);
  return $result;
}

print_r(combinations(array(20,20,22,24), 3));
?>

OUTPUT:

Array ( [0] => Array ( [0] => 20 
                       [1] => 20 
                       [2] => 22 ) 
        [1] => Array ( [0] => 20 
                       [1] => 20 
                       [2] => 24 ) 
        [2] => Array ( [0] => 20 
                       [1] => 22 
                       [2] => 24 ) 
        [3] => Array ( [0] => 20 
                       [1] => 22 
                       [2] => 24 ) ) 


Answer 2:

PEAR包Math_Combinatorics使这类问题很容易。 这需要相对较少的代码,它的简单和直接,这是很容易阅读。

$ cat code/php/test.php
<?php
$input = array(20, 20, 22, 24);

require_once 'Math/Combinatorics.php';

$c = new Math_Combinatorics;
$combinations = $c->combinations($input, 3);
for ($i = 0; $i < count($combinations); $i++) {
  $vals = array_values($combinations[$i]);
  $s = implode($vals, ", ");
  print $s . "\n";
}
?>

$ php code/php/test.php
20, 20, 22
20, 20, 24
20, 22, 24
20, 22, 24

如果我有这个打包的功能,我会做这样的事情。

function combinations($arr, $num_at_a_time) 
{
    include_once 'Math/Combinatorics.php';

    if (count($arr) < $num_at_a_time) {
        $arr_count = count($arr);
        trigger_error(
            "Cannot take $arr_count elements $num_at_a_time " 
            ."at a time.", E_USER_ERROR
        );
    }

    $c = new Math_Combinatorics;
    $combinations = $c->combinations($arr, $num_at_a_time);

    $return = array();
    for ($i = 0; $i < count($combinations); $i++) {
        $values = array_values($combinations[$i]);
        $return[$i] = $values;
    }
    return $return;
}

将返回一个数组的数组。 为了获取文本。 。 。

<?php
  include_once('combinations.php');

  $input = array(20, 20, 22, 24);
  $output = combinations($input, 3);

  foreach ($output as $row) {
      print implode($row, ", ").PHP_EOL;
  }
?>
20, 20, 22
20, 20, 24
20, 22, 24
20, 22, 24


Answer 3:

这个想法很简单。 假设你知道如何置换,然后如果你在一组它成为一个组合保存这些排列。 设置由定义采用重复值的照顾。 设置或一个HashSet PHP的euqivalent是SplObjectStorage和ArrayList是数组。 它不应该是很难改写。 我有在Java中实现:

public static HashSet<ArrayList<Integer>> permuteWithoutDuplicate(ArrayList<Integer> input){
          if(input.size()==1){
              HashSet<ArrayList<Integer>> b=new HashSet<ArrayList<Integer>>();
              b.add(input);
              return b;
          }
          HashSet<ArrayList<Integer>>ret= new HashSet<ArrayList<Integer>>();
          int len=input.size();
          for(int i=0;i<len;i++){
              Integer a = input.remove(i);
              HashSet<ArrayList<Integer>>temp=permuteWithoutDuplicate(new ArrayList<Integer>(input));
              for(ArrayList<Integer> t:temp)
                  t.add(a);
              ret.addAll(temp);
              input.add(i, a);
          }
          return ret;
      }


Answer 4:

为什么不直接使用二进制? 至少这样的简单,很容易理解的每行代码都这样做? 这里有一个功能我在一个项目我认为这是相当整洁,写了自己!

function search_get_combos($array){
$bits = count($array); //bits of binary number equal to number of words in query;
//Convert decimal number to binary with set number of bits, and split into array
$dec = 1;
$binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
while($dec < pow(2, $bits)) {
    //Each 'word' is linked to a bit of the binary number.
    //Whenever the bit is '1' its added to the current term.
    $curterm = "";
    $i = 0;
    while($i < ($bits)){
        if($binary[$i] == 1) {
            $curterm[] = $array[$i]." ";
        }
        $i++;
    }
    $terms[] = $curterm;
    //Count up by 1
    $dec++;
    $binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
}
return $terms;
} 

对于你的榜样,这个输出:

Array
(
    [0] => Array
        (
            [0] => 24 
        )
    [1] => Array
        (
            [0] => 22 
        )
    [2] => Array
        (
            [0] => 22 
            [1] => 24 
        )
    [3] => Array
        (
            [0] => 20 
        )
    [4] => Array
        (
            [0] => 20 
            [1] => 24 
        )
    [5] => Array
        (
            [0] => 20 
            [1] => 22 
        )
    [6] => Array
        (
            [0] => 20 
            [1] => 22 
            [2] => 24 
        )
    [7] => Array
        (
            [0] => 20 
        )
    [8] => Array
        (
            [0] => 20 
            [1] => 24 
        )
    [9] => Array
        (
            [0] => 20 
            [1] => 22 
        )
    [10] => Array
        (
            [0] => 20 
            [1] => 22 
            [2] => 24 
        )
    [11] => Array
        (
            [0] => 20 
            [1] => 20 
        )
    [12] => Array
        (
            [0] => 20 
            [1] => 20 
            [2] => 24 
        )
    [13] => Array
        (
            [0] => 20 
            [1] => 20 
            [2] => 22 
        )
    [14] => Array
        (
            [0] => 20 
            [1] => 20 
            [2] => 22 
            [3] => 24 
        )
)


Answer 5:

有同样的问题,发现不同和位,更快的解决方案:

function bitprint($u) {
    $s = array();
    for ($n=0; $u; $n++, $u >>= 1){
        if ($u&1){
            $s [] = $n;
        }
    }
    return $s;
}
function bitcount($u) {
    for ($n=0; $u; $n++, $u = $u&($u-1));
    return $n;
}
function comb($c,$n) {
    $s = array();
    for ($u=0; $u<1<<$n; $u++){
        if (bitcount($u) == $c){
            $s [] = bitprint($u);
        }
    }
    return $s;
}

这一个从0生成整数的所有大小为m的组合到n-1,因此,例如M = 2,N = 3和调用梳(2,3)将产生:

0 1
0 2
1 2

它给你的索引位置,所以很容易通过索引指向数组元素。

编辑:具有输入梳(30,5)失败。 不知道为什么,任何人任何想法?



Answer 6:

清理使用strrev和/ foreach循环阿迪布拉德菲尔德的sugestion,只有获得独特的效果。

function search_get_combos($array = array()) {
sort($array);
$terms = array();

for ($dec = 1; $dec < pow(2, count($array)); $dec++) {
    $curterm = array();
    foreach (str_split(strrev(decbin($dec))) as $i => $bit) {
        if ($bit) {
            $curterm[] = $array[$i];
        }
    }
    if (!in_array($curterm, $terms)) {
        $terms[] = $curterm;
    }
}

return $terms;
}


文章来源: PHP Find All (somewhat) Unique Combinations of an Array