Codice in materia di trattamento più di 2 valori
<?php
function keyMultiSort(&$array,
$key,
$reverse = false,
$priority_last = false,
$save_key = true,
Callable $func = null)
{
if ($func === null)
{
$func = function ($first, $second) use ($key, $reverse, $priority_last)
{
if (!isset($first[$key]))
{
return ($reverse === false) ? -1 : 1;
}
if (!isset($second[$key]))
{
return ($reverse === false) ? 1 : -1;
}
if ($first[$key] > $second[$key])
{
return ($reverse === false) ? 1 : -1;
}
if ($first[$key] < $second[$key])
{
return ($reverse === false) ? -1 : 1;
}
if ($first[$key] === $second[$key])
{
return ($priority_last === false) ? 1 : -1;
}
return 0;
};
}
if ($save_key)
{
uasort($array, $func);
}
else
{
usort($array, $func);
}
}
$array = [
['foo', 'bar', 'test'],
['boo', 'bar'],
['goo', 'bar'],
['hoo', 'doo', 'test', 'test2'],
['foo', 'manchu'],
['moo', 'bar'],
['too', 'bar'],
['foo', 'fighters'],
['blue kazoo', 'bar', 'test'],
];
$pairs = [];
$str = '';
foreach($array as $item)
{
foreach($item as $key=>$elm)
{
foreach($item as $key2=>$elm2)
{
if($key !== $key2)
{
if(!isset($pairs[$elm]['count']))
{
$pairs[$elm]['count'] = 1;
}
else
{
$pairs[$elm]['count']++;
}
$pairs[$elm]['elements'][] = $elm2;
}
}
}
keyMultiSort($pairs, 'count', true);
}
//var_dump($pairs);
$remove = [];
foreach($pairs as $elm=>$item)
{
$remove[] = $elm;
$elements = array_diff($item['elements'], $remove);
if(empty($elements))
{
if (in_array($elm, $remove))
{
continue;
}
$str .= $elm.PHP_EOL;
}
else
{
$str .= $elm.' AND ('.implode(' OR ', array_unique($elements)).')'.PHP_EOL;
}
}
var_dump($str);
Risposta:
string(184) "bar AND (foo OR test OR boo OR goo OR moo OR too OR blue kazoo)
test AND (foo OR hoo OR doo OR test2 OR blue kazoo)
foo AND (manchu OR fighters)
hoo AND (doo OR test2)
doo AND (test2)
"
P.S. Spero di aver capito bene il compito ...
UPDATE codice Aggiunto che non ignora "valori singoli". Ho cambiato la logica:
...
['"yellow balloon"', 'foo', 'bar', 'baz', 'qut'],
...
ritorno:
...
qut AND ("yellow balloon" OR baz)
baz AND ("yellow balloon")
...
Mi sembra, per questo compito, che è corretta (per le condizioni di combinare più di 2 valori).
function keyMultiSort(&$array,
$key,
$reverse = false,
$priority_last = false,
$save_key = true,
Callable $func = null)
{
if ($func === null)
{
$func = function ($first, $second) use ($key, $reverse, $priority_last)
{
if (!isset($first[$key]))
{
return ($reverse === false) ? -1 : 1;
}
if (!isset($second[$key]))
{
return ($reverse === false) ? 1 : -1;
}
if ($first[$key] > $second[$key])
{
return ($reverse === false) ? 1 : -1;
}
if ($first[$key] < $second[$key])
{
return ($reverse === false) ? -1 : 1;
}
if ($first[$key] === $second[$key])
{
return ($priority_last === false) ? 1 : -1;
}
return 0;
};
}
if ($save_key)
{
uasort($array, $func);
}
else
{
usort($array, $func);
}
}
$array = [
['foo', 'bar', 'test'],
['boo', 'bar'],
['goo', 'bar'],
['hoo', 'doo', 'test', 'test2'],
['foo', 'manchu'],
['moo', 'bar'],
['too', 'bar'],
['foo', 'fighters'],
['"blue kazoo"', 'bar', 'test'],
['"red panda"', 'bar', 'test'],
['"yellow balloon"', 'foo', 'bar', 'baz', 'qut'],
['"red panda"', 'fighters', 'moo'],
['"foo fighters"'],
['foo'],
['bar'],
];
$pairs = [];
$singles = [];
$str = '';
foreach ($array as $item)
{
foreach ($item as $key => $elm)
{
if(count($item) === 1)
{
$singles[$elm] = 1;
}
else
{
if (!isset($pairs[$elm]))
{
$pairs[$elm]['count'] = 0;
$pairs[$elm]['elements'] = [];
}
foreach ($item as $key2 => $elm2)
{
if ($key !== $key2)
{
$pairs[$elm]['count']++;
$pairs[$elm]['elements'][] = $elm2;
}
}
}
}
keyMultiSort($pairs, 'count', true);
}
//var_dump($pairs);exit;
$remove = [];
foreach ($pairs as $elm => $item)
{
$remove[] = $elm;
$elements = array_diff($item['elements'], $remove);
$elements = array_unique($elements);
if (!empty($elements)){
$str .= $elm.' AND ('.implode(' OR ', $elements).')'.PHP_EOL;
}
}
foreach ($singles as $elm => $item)
{
$str .= $elm.PHP_EOL;
}
var_dump($str);
Risposta:
string(421) "bar AND (foo OR test OR boo OR goo OR moo OR too OR "blue kazoo" OR "red panda" OR "yellow balloon" OR baz OR qut)
test AND (foo OR hoo OR doo OR test2 OR "blue kazoo" OR "red panda")
foo AND (manchu OR fighters OR "yellow balloon" OR baz OR qut)
"red panda" AND (fighters OR moo)
qut AND ("yellow balloon" OR baz)
baz AND ("yellow balloon")
test2 AND (hoo OR doo)
fighters AND (moo)
doo AND (hoo)
"foo fighters"
foo
bar
"
P.S. A mio parere, questo problema non si applica alla realtà
Qualsiasi parola o frase citata può essere separata da un OR. Nel mio esempio poiché 'foo bar' e' boo bar' condividono 'bar' in comune, possono diventare' (foo OR boo) AND bar' – OneCleverMonkey
Aggiunta una taglia per migliorare (o cercare nuove) risposte che risolvono ricorsivamente per _n_ numero di parole per query (non solo 2) e conserva le virgolette. – Ryan
http://blog.burntsushi.net/transducers/#finite-state-machines-as-data-structures – Jacob