2

So, I am trying to get a list of every possible combination of a set of words.

With the input text "1, 2" and the values being ("1" => "a", "b", "c") and ("2" => "d", "e"), I would get something like:

a, d
b, d
c, d
a, e
b, e
c, e

With the code I have right now, I only get:

a, d
b, d
c, d

How can I get around this?

Code:

foreach ($words as $word)
{
    for ($i = 0; $i < count($array); $i++) //For every value
    {
        $key = array_keys($array[$i])[0];
        if ($word === $key)
        {
            $syn = explode("|", $array[$i][$key]); //Get all synonyms
            foreach ($syn as $s) //For each synonym within
            {

                $potential[] = implode(" ", str_replace($key, $s, $words));
            }
        }
    }
}

The procedure is for every word in the input text, we want to go through our entire array of values. In there, we have other arrays ("original" => "synonyms"). From there, we loop through every synonym and add it to a list of potential combinations.

Adam M
  • 113
  • 3
  • 13

2 Answers2

2

Assuming that 1 and 2 are both array you can do nested for loops to get every possible combination.

$one = array("a", "b", "c");
$two = array("d", "e");


$final_array = array();

for($a = 0; $a<sizeof($one); $a++) 
{
    for($b = 0; $b<sizeof($two); $b++) 
    {

            $final_array[] = $one["$a"] . $two["$b"];
    }
}

print_r($final_array);

This will print out

Array ( [0] => ad 
        [1] => ae 
        [2] => bd 
        [3] => be 
        [4] => cd 
        [5] => ce )

Hope this was what you were looking for.

Cesarg2199
  • 569
  • 1
  • 6
  • 18
  • This doesn't help me as I have no idea how many arrays I am going to have. I may have one, I may have one hundred. Hence why I need some sort of function that can handle any amount :) – Adam M Jul 18 '15 at 10:18
  • `foreach` loops would probably be better than `for` loops calling `sizeof` repeatedly. – spenibus Jul 18 '15 at 23:29
2

There are a few steps involved:

  1. narrow down the list of synonyms to only those found in the string
  2. create a template from which to build the final sentences
  3. get all synonym combinations and apply them to the template

The following will do that:

$dict = [
    '1' => ['a', 'b', 'c'],
    '2' => ['d', 'e'],
];

$str = '2, 1';

class SentenceTemplate implements IteratorAggregate
{
    private $template;
    private $thesaurus;

    public function __construct($str, $dict)
    {
        $this->thesaurus = [];

        $this->template = preg_replace_callback('/\w+/', function($matches) use ($dict) {
            $word = $matches[0];
            if (isset($dict[$word])) {
                $this->thesaurus[] = $dict[$word];
                return '%s';
            } else {
                return $word;
            }
        }, $str);
    }

    public function getIterator()
    {
        return new ArrayIterator(array_map(function($args) {
            return vsprintf($this->template, $args);
        }, $this->combinations($this->thesaurus)));
    }

    private function combinations($arrays, $i = 0) {
        if (!isset($arrays[$i])) {
            return array();
        }
        if ($i == count($arrays) - 1) {
            return $arrays[$i];
        }

        // get combinations from subsequent arrays
        $tmp = $this->combinations($arrays, $i + 1);

        $result = array();

        // concat each array from tmp with each element from $arrays[$i]
        foreach ($arrays[$i] as $v) {
            foreach ($tmp as $t) {
                $result[] = is_array($t) ? array_merge(array($v), $t) : array($v, $t);
            }
        }

        return $result;
    }
}

$sentences = new SentenceTemplate($str, $dict);
foreach ($sentences as $sentence) {
    echo "$sentence\n";
}

Demo

Community
  • 1
  • 1
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • This doesn't seem to work for me. Data: `dict ( "hello" => array("hey", "whats up"...), "name" => array("nomenclature"...))` and `str = "hello my name is"` - The only result I get is `0=Array my is` – Adam M Jul 18 '15 at 10:17
  • @AdamM I'll test it again with your input and see what I've missed :) – Ja͢ck Jul 18 '15 at 10:38
  • @AdamM I ran your input with my code and it works okay; I've made a small update because I wasn't using `$str` at the bottom. – Ja͢ck Jul 18 '15 at 23:00