-2

I have a string composed by many letters, at some point, one letter from a group can be used and this is represented by letters enclosed in []. I need to expand these letters into its actual strings.

From this:

$str = 'ABCCDF[GH]IJJ[KLM]'

To this:

$sub[0] = 'ABCCDFGIJJK';
$sub[1] = 'ABCCDFHIJJK';
$sub[2] = 'ABCCDFGIJJL';
$sub[3] = 'ABCCDFHIJJL';
$sub[4] = 'ABCCDFGIJJM';
$sub[5] = 'ABCCDFHIJJM';

UPDATE:

Thanks to @Barmar for the very valuable suggestions.

My final solution is:

$str = '[GH]DF[IK]TF[ADF]';

function parseString(string $str) : array
{
    $i = 0;
    $is_group = false;
    $sub = array();
    $chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);

    foreach ($chars as $key => $value)
    {
        if(ctype_alpha($value))
        {
            if($is_group){
                $sub[$i][] = $value;
            } else {
                if(!isset($sub[$i][0])){
                    $sub[$i][0] = $value;
                } else {
                    $sub[$i][0] .= $value;
                }
            }
        } else {
            $is_group = !$is_group;
            ++$i;
        }
    }
    return $sub;
}

The recommended function for combinations is (check the related post):

function array_cartesian_product($arrays)
{
    $result = array();
    $arrays = array_values($arrays);
    $sizeIn = sizeof($arrays);
    $size = $sizeIn > 0 ? 1 : 0;
    foreach ($arrays as $array)
        $size = $size * sizeof($array);
    for ($i = 0; $i < $size; $i++) {
        $result[$i] = array();
        for ($j = 0; $j < $sizeIn; $j++)
            array_push($result[$i], current($arrays[$j]));
        for ($j = ($sizeIn - 1); $j >= 0; $j--) {
            if (next($arrays[$j]))
                break;
            elseif (isset($arrays[$j]))
                reset($arrays[$j]);
        }
    }
    return $result;
}

Check the solution with:

$combinations = array_cartesian_product(parseString($str));
$sub = array_map('implode', $combinations);
var_dump($sub);
micros
  • 3
  • 4
  • Turn the strings in square brackets into arrays. Then get all the combinations of the arrays. – Barmar Feb 01 '19 at 02:58
  • What are you doing with the `sub`s later? Maybe just using `$str` in a regex context would work – user3783243 Feb 01 '19 at 03:06
  • Possible duplicate of [How to I can split match letter in string PHP](https://stackoverflow.com/questions/54472641/how-to-i-can-split-match-letter-in-string-php) – user3783243 Feb 01 '19 at 04:25
  • @barmar Thanks for your advice but is not totally clear for me. What you suggest is to break the string in arrays like this $str[0] = 'ABCCDF' $str[1] = 'G' $str[2] = 'H' $str[3] = 'IJJ' $str[4] = 'K' $str[5] = 'L' $str[6] = 'M' ... and then do the permutations? I think I can do the arrys, could you please give me some advice for the permutations? – micros Feb 01 '19 at 16:17
  • @user3783243 I need the expanded strings to search inside thos strings, for example, I want to know if `'DFIJ'` belogns to this rule – micros Feb 01 '19 at 16:23
  • What is the rule? Where does `DFIJ ` come from? Also why does another user have the same code as you? – user3783243 Feb 01 '19 at 16:26
  • Hello, @user3783243 The `DFIJ` comes from the question about what I am going to do with these expanded strings. I want to verify the existence of many random strings inside this expanded strings. That's an example. Other could be `AADD` or `ABCM` I think the best way is to expand the strings instead to do some regular expression search. I posted this question in another two forums. Probably someone is trying to solve my question but is not me. – micros Feb 01 '19 at 16:49
  • None of those match the expanded strings though. How do they relate? – user3783243 Feb 01 '19 at 16:58
  • @user3783243 Probably was a wrong example. I'll try to make a better one: Suppose I want to check what of this strings is included (as a partial or full match) in one of the expanded strings. Then `CDFHIJ` is a match with $sub[1], `ABCCDFH` is a match with $sub[1], $sub[3] and $sub[5] and `ABCM` doesn't match. – micros Feb 01 '19 at 17:24
  • `CDFHIJ` matches 1, 3, and 5 as well. Are the constants optional, e.g. `ABCCDF` and `IJJ` may/may not be present? Because I wouldn't normally say `CDFHIJ` == `ABCCDFHIJJK`. – user3783243 Feb 01 '19 at 17:35
  • Yes, I need the expanded strings to check if a random string is CONTAINED in some way in at least one (1) of these expanded strings. – micros Feb 01 '19 at 19:48

1 Answers1

0

Convert your string into a 2-dimensional array. The parts outside brackets become single-element arrays, while each bracketed trings becomes an array of single characters. So your string would become:

$array = 
    array(array('ABCCDF'),
          array('G', 'H', 'I'),
          array('IJJ'),
          array('K', 'L', 'M'));

Then you just need to compute all the combinations of those arrays; use one of the answers at How to generate in PHP all combinations of items in multiple arrays. Finally, you concatenate each of the resulting arrays with implode to get an array of strings.

$combinations = combinations($array);
$sub = array_map('implode', $combinations);
Barmar
  • 741,623
  • 53
  • 500
  • 612