SO,
问题
第一种情况
我有一个带有一些值的数组 - 首先,让它们都是字符串(或者可以简单地视为字符串)。例如:
$rgData = ['foo', 'feo', 'bar', 'baz', 'bee'];
现在,我想从中创建唯一的数组,其中两个项之间的Levenshtein distance小于2。如果$x
,则$y
和levenshtein($x, $y) < 2
项视为相等。例如,foo
和feo
相同,还有bar
和baz
- 但不是bar
和bee
。
第二种情况
我有一个点坐标为[x, y]
的数组,例如:
$rgData = [[0, 0.1], [-5, 4.5], [0, 0.5], [-5.5, 4.5]];
现在,我想从中创建唯一的数组,其中两点之间的距离小于1。如果$x
$y
和pow((pow($x[0]-$y[0], 2) + pow($x[1]-$y[1],2)), 0.5)<1
被视为相等
很明显,这两种情况都可以通过某种函数来解决,这种函数类似于标准的PHP array_unique() - 但它接受比较函数来检查项是否相等。我的问题是关于这个功能。
我的方法
现在,我有最简单的解决方案:
function array_uunique($rgData, $fnCompare=null)
{
if(!isset($fnCompare))
{
return array_unique($rgData);
}
if(!is_callable($fnCompare))
{
return null;
}
if(!count($rgData))
{
return array();
}
$rgResult = array();
foreach($rgData as $mItem)
{
foreach($rgResult as $mTest)
{
if(!call_user_func_array($fnCompare, [$mItem, $mTest]))
{
continue 2;
}
}
$rgResult[]=$mItem;
}
return $rgResult;
}
-it接受回调作为第二个参数,并使用此比较规则返回不等于的元素,即对于levenshtein,所描述的结果将是:
$rgResult = array_uunique(['foo', 'feo', 'bar', 'baz', 'bee'], function($x, $y)
{
return levenshtein($x, $y)>1; //or !levenshtein($x, $y)<2
});
- 这将导致
array(3) { [0]=> string(3) "foo" [1]=> string(3) "bar" [2]=> string(3) "bee" }
- 您可以使用this fiddle来测试它。
具体细节信息
如上所述,这是最简单的方式,但它包含2个嵌套的依赖循环。因此,这种构造的复杂性将是O(N^2)
- 这很难过 - 并且对我不起作用,特别是如果比较函数操作成本太高 - 因为我将在数据数组中有大量元素(~1E5。 .1E6至少)。
我的问题是 - 如何改善这个?可能还有另一个好的算法吗?或者可能是我的代码可以以某种方式改进?
更新(基于下面的好评):我知道在一般情况下,这样的问题会导致transitive function问题,例如xFy = yFz => xFz
- 例如, levenshtein()
不具有传递性。因此,整个结果将至少取决于常见情况中的项目顺序(但不仅仅是它) - 现在对我来说这不是问题,因为我确信我的数据顺序和内容(或者,至少,如果bar
或baz
将通过levenshtein
比较返回,则不是问题。所以,我的目标是最小化比较次数(因此比较函数是否具有传递性,或者没有任何变化,我认为,因为我想优化甚至重新创建比较算法本身)
答案 0 :(得分:1)
输入set = {a,b,c,...} matrice,
a b c . . .
a 1
b 1 1
C 0 0 1
. 1
. 1
. 1
1如果两个元素在同一组中,1s在对角线反射属性,计算olny下三角形couse symetric属性。在第n行,如果找到匹配,则开始与cols比较,放置1,并删除第n列,形成进一步的比较。我希望这是可以理解的。
最坏情况:如果每个组都有一个元素。