4

Sorry for the title as it looks like most of the other questions about combining arrays, but I don't know how to write it more specific.

I need a PHP function, which combines the entries of one array (dynamic size from 1 to any) to strings in every possible combination.

Here is an example with 4 entries:

$input = array('e1','e2','e3','e4);

This should be the result:

$result = array(
    0 => 'e1',
    1 => 'e1-e2',
    2 => 'e1-e2-e3',
    3 => 'e1-e2-e3-e4',
    4 => 'e1-e2-e4',
    5 => 'e1-e3',
    6 => 'e1-e3-e4',
    7 => 'e1-e4'
    8 => 'e2',
    9 => 'e2-e3',
   10 => 'e2-e3-e4',
   11 => 'e2-e4',
   12 => 'e3',
   13 => 'e3-e4',
   14 => 'e4'
);

The sorting of the input array is relevant as it affects the output. And as you see, there should be an result like e1-e2 but no e2-e1.

It seems really complicated, as the input array could have any count of entries. I don't even know if there is a mathematical construct or a name which describes such a case.

Has anybody done this before?

Lucker
  • 43
  • 4

3 Answers3

2

You are saying that there might be any number of entries in the array so I'm assuming that you aren't manually inserting the data and there would be some source or code entering the data. Can you describe that? It might be easier to directly store it as per your requirement than having an array and then changing it as per your requirement

This might be helpful Finding the subsets of an array in PHP

Chhitij
  • 111
  • 7
  • Wow, that linked question or better say answer, does the right thing. It needs some modification to output strings instead of combined arrays, but it looks like it works. I need this for a service, which selects the right objects (complex calculations) from user selected properties. I can't change the service itself, but the stored objects and options. For example a red car has the options `car` and `car-red`. If the the user wants any car, I send the option `car`, if he wants a red car, I have to send `car-red`. – Lucker Dec 03 '17 at 14:16
  • I'm sorry for posting this as an answer but I didn't have 50+ reputation to make a comment on the author's post at the time of sharing this – Chhitij Dec 04 '17 at 07:13
0

I have managed to bodge together a code that creates the output you want from the input you have.
I think I have understood the logic of when and why each item looks the way it deos. But Im not sure, so test it carefully before using it live.

I have a hard time explaining the code since it's really a bodge.

But I use array_slice to grab the values needed in the strings, and implode to add the - between the values.

$in = array('e1','e2','e3','e4');

//$new =[];
$count = count($in);
Foreach($in as $key => $val){
    $new[] = $val; // add first value

    // loop through in to greate the long incrementing string
    For($i=$key; $i<=$count-$key;$i++){
        if($key != 0){
             $new[] = implode("-",array_slice($in,$key,$i));
        }else{
            if($i - $key>1) $new[] = implode("-",array_slice($in,$key,$i));
        }
    }

    // all but second to last except if iteration has come to far
    if($count-2-$key >1) $new[] = Implode("-",Array_slice($in,$key,$count-2)). "-". $in[$count-1];

    // $key (skip one) next one. except if iteration has come to far
    If($count-2-$key >1) $new[] = $in[$key] . "-" . $in[$key+2];

    // $key (skip one) rest of array except if iteration has come to far
    if($count-2-$key > 1) $new[] = $in[$key] ."-". Implode("-",Array_slice($in,$key+2));

    // $key and last item, except if iteration has come to far
    if($count-1 - $key >1) $new[] = $in[$key] ."-". $in[$count-1];

}


$new = array_unique($new); // remove any duplicates that may have been created

https://3v4l.org/uEfh6

Andreas
  • 24,301
  • 5
  • 27
  • 57
  • Thank you very much for your time! It seems to work until 4 input values. But unfortunately when I add a 5th value, there are some combinations missing. Maybe I come to a solution with your groundwork. – Lucker Dec 03 '17 at 13:44
  • What combination is missing? – Andreas Dec 03 '17 at 14:01
  • on `$in = array('e1','e2','e3','e4','e5');` ist for example `e1-e3-e4` or `e4-e5` missing – Lucker Dec 03 '17 at 14:11
  • Why would there be an `e1-e3-e4`? I think your question is very vague on what and why the output should be the way it is. – Andreas Dec 03 '17 at 14:19
0

here is a modificated version of Finding the subsets of an array in PHP

function powerSet($in,$minLength = 1) { 
    $count = count($in); 
    $keys = array_keys($in);
    $members = pow(2,$count); 
    $combinations = array(); 
    for ($i = 0; $i < $members; $i++) { 
       $b = sprintf("%0".$count."b",$i); 
       $out = array(); 
       for ($j = 0; $j < $count; $j++) { 
          if ($b{$j} == '1') {
            $out[] = $keys[$j]; 
          }
       } 
       if (count($out) >= $minLength) { 
          $combinations[] = $out; 
       } 
    } 
    $result = array();
    foreach ($combinations as $combination) {
        $values = array();
        foreach ($combination as $key) {
            $values[$key] = $in[$key];
        }
        $result[] = implode('-', $values);
    }
    sort($result);
    return $result;
 }

This seems to work.

Lucker
  • 43
  • 4