所以,
问题
从 SQL 我得到一个带有字符串的数组(平面数组) - 让它成为
$rgData = ['foo', 'bar', 'baz', 'bee', 'feo'];
现在,我想获得这个数组的对和三元组的可能组合(以及,在常见情况下,4 个元素的组合)。更具体地说:我的意思是数学意义上的组合(没有重复),即那些计数等于
- 所以对于上面的数组,对和三胞胎都是 10。
我的方法
我已经开始将可能的值映射到可能的数组选定项。我当前的解决方案是指出一个元素是否被选为“1”,否则为“0”。对于上面的示例,这将是:
foo bar baz 蜜蜂 feo 0 0 1 1 1 -> [baz,蜜蜂,feo] 0 1 0 1 1 -> [酒吧,蜜蜂,feo] 0 1 1 0 1 -> [bar, baz, feo] 0 1 1 1 0 -> [酒吧,巴兹,蜜蜂] 1 0 0 1 1 -> [foo, 蜜蜂, feo] 1 0 1 0 1 -> [foo, baz, feo] 1 0 1 1 0 -> [foo, baz, 蜜蜂] 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 的情况(所以它是最大的,找不到更多的)。如果找到,进入第二步
- 转到字符串中“01”的最右侧位置。将其切换到“10”,然后将所有比找到的“01”位置更右侧的零移动到左侧。比如
01110
:“01”最右边的位置是0,那么我们首先把这个“01”切换到“10”。字符串现在仍然是10110
。现在,转到右边部分(它没有10
部分,所以它从 0+2=2-nd 符号开始),并将所有零向左移动,即110
will be011
。结果,我们将10
+011
=10111
作为 的下一个关联01110
。
我在这里发现了类似的问题——但是 OP 想要有重复的组合,而我希望它们没有重复。
问题
我的问题是关于两点:
- 对于我的解决方案,是否有另一种方法可以更有效地产生下一个位集?
- 可能有更简单的解决方案吗?这似乎是标准问题。