SO,Получить возможные комбинации массива
Проблема
С SQL я получаю массив строк (плоский массив) - пусть это будет
$rgData = ['foo', 'bar', 'baz', 'bee', 'feo'];
Теперь я хочу для получения возможных комбинаций пар и триплетов этого массива (и, в общем случае, комбинаций из 4 элементов e tc). Чтобы быть более конкретным: Я имею в виду combinations в математическом смысле (без дубликатов), то есть те, которые рассчитывать равна
-SO для массива выше, что будет 10 для обеих пар и триплетов.
Мой подход
Я начал с отображения возможных значений для возможных массива выбранных элементов. Мое текущее решение - указать, если элемент выбран как «1», а «0» - в противном случае. Для образца выше, который будет:
foo bar baz bee feo 0 0 1 1 1 -> [baz, bee, feo] 0 1 0 1 1 -> [bar, bee, feo] 0 1 1 0 1 -> [bar, baz, feo] 0 1 1 1 0 -> [bar, baz, bee] 1 0 0 1 1 -> [foo, bee, feo] 1 0 1 0 1 -> [foo, baz, feo] 1 0 1 1 0 -> [foo, baz, bee] 1 1 0 0 1 -> [foo, baz, feo] 1 1 0 1 0 -> [foo, bar, bee] 1 1 1 0 0 -> [foo, bar, baz]
И все, что мне нужно сделать, это как-то создать желаемый набор бит. Вот мой код в PHP:
function nextAssoc($sAssoc)
{
if(false !== ($iPos = strrpos($sAssoc, '01')))
{
$sAssoc[$iPos] = '1';
$sAssoc[$iPos+1] = '0';
return substr($sAssoc, 0, $iPos+2).
str_repeat('0', substr_count(substr($sAssoc, $iPos+2), '0')).
str_repeat('1', substr_count(substr($sAssoc, $iPos+2), '1'));
}
return false;
}
function getAssoc(array $rgData, $iCount=2)
{
if(count($rgData)<$iCount)
{
return null;
}
$sAssoc = str_repeat('0', count($rgData)-$iCount).str_repeat('1', $iCount);
$rgResult = [];
do
{
$rgResult[]=array_intersect_key($rgData, array_filter(str_split($sAssoc)));
}
while($sAssoc=nextAssoc($sAssoc));
return $rgResult;
}
-Мы выбрали сохранение своих битов в качестве обычной строки. Мой алгоритм для создания следующей ассоциации:
- Попробуйте найти "01". Если не найден, то это 11..100..0 case (так что это максимум, больше не может быть найдено). Если будет найдена, перейдите на второй этап
- Перейти к most right позиция "01" в строке. Переключите его в положение «10», а затем переместите все нули, которые более резкие, чем «позиция 01» - слева. Например,
01110
: самое правильное положение «01» равно 0, поэтому сначала мы переключаем этот «01» на «10». Строка теперь подоконника10110
. Теперь, перейдите в правую часть (это без10
часть, поэтому она начинается с 0 + 2 = 2-й символ) и перемещает все нули влево, то есть110
будет011
. В результате у нас есть10
+011
=10111
как следующая ассоциация для01110
.
Я нашел аналогичную проблему here - но там OP хочет сочетания с дубликатами, в то время как я хочу их без дублирования.
Вопрос
Мой вопрос о двух точках:
- Для моего решения, может быть, есть другой способ, чтобы произвести следующий бит установлен более эффективным?
- Может быть, есть более простые решения для этого? Кажется, это стандартная проблема.
Возможный дубликат [Алгоритм для возврата всех комбинаций k элементов из n] (http : //stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n) – ElKamina
Ничего себе, это выглядит интересно, спасибо @ElKamina –
Я думал, что мой ответ был в порядке, с хороший баланс между чистым PHP-кодом и скоростью. Вы просто пропустили это? –