在我添加澄清之前,这里有一些伪数据。我需要迭代的数组是这样的:
$ipBodies = array(
'1.2.3.4' => array(
array('id' => 1, 'body' => 'asdfasdfasdf_X'),
array('id' => 2, 'body' => 'asdfasdfasdf_Y'),
array('id' => 3, 'body' => '123456789_X'),
array('id' => 4, 'body' => '123456789_Y'),
),
'5.6.7.8' => array(
array('id' => 13, 'body' => 'foobarbaz_X'),
array('id' => 14, 'body' => 'foobarbaz_Y'),
array('id' => 15, 'body' => 'adsflkjlsdfjlkjlkasdfj'),
array('id' => 16, 'body' => 'foobarbaz_Z'),
),
);
因此,从这个示例数据中,您可以看到在1.2.3.4数组中有两组唯一的"模糊重复",而在5.6.7.8数组中只有1组"模糊重复"。
在真实数据中,一切都按比例放大。主数组将有数百个ip地址,这些数组可能有数百个成员。body
部分在实际数据中更大。
我认为我需要运行每个ip地址数组,并创建每个组合的新数组到一个新数组,例如$pairs
,然后运行similar_text
(似乎对此工作得很好),以找到重复项,但创建这些对集将是昂贵的我相信。我认为$pairs
数组计数最终将是数组计数的阶乘,随着数组大小的增加,它可能变得非常大。
我想我想结束与数组$dupes(基于上面的样本数据)应该看起来像这样:
$dupes = array(
'1.2.3.4' => array(
array('1', '2'),
array('3', '4'),
),
'5.6.7.8' => array(
array('13', '14', '16'),
),
);
我真的需要一些帮助和建议,这样我就可以开始解决这个问题了。天啊,我希望我的解释有道理。如果没有,请告诉我,我将澄清。
如果可能的话,我建议使用levenshtein而不是similar_text,因为它是一个更快的算法。
算法复杂度为O(m*n),其中n、m为str1和str2的长度(与similar_text()相比相当好),这是O(max(n,m)**3),但仍然很昂贵)。
下面的代码使用关联数组将每个元素放入到ip['body']
的距离为<2(这意味着同一桶内的匹配最多有1个不同的字符,根据需要进行更改)。一旦所有元素都被放入各自的桶中,每个只有1个元素的桶将被丢弃。
$ipBodies = array(
'1.2.3.4' => array(
array('id' => 1, 'body' => 'asdfasdfasdf_X'),
array('id' => 2, 'body' => 'asdfasdfasdf_Y'),
array('id' => 3, 'body' => '123456789_X'),
array('id' => 4, 'body' => '123456789_Y'),
),
'5.6.7.8' => array(
array('id' => 13, 'body' => 'foobarbaz_X'),
array('id' => 14, 'body' => 'foobarbaz_Y'),
array('id' => 15, 'body' => 'adsflkjlsdfjlkjlkasdfj'),
array('id' => 16, 'body' => 'foobarbaz_Z'),
),
);
$counts = [];
foreach($ipBodies as $groupName => $group) {
$counts[$groupName] = [];
foreach($group as $key => $ip) {
foreach($counts[$groupName] as $countGroup => $groupCount) {
if(levenshtein($ip['body'],$countGroup) < 2) {
$counts[$groupName][$countGroup][] = $ip['id'];
continue 2;
}
}
$counts[$groupName][$ip['body']] = [$ip['id']];
}
}
//remove elements that appear just once
foreach($counts as $groupName => &$groupCounts) {
foreach($groupCounts as $k => &$v) {
if(count($v) < 2) {
unset($counts[$groupName][$k]);
}
}
$counts[$groupName] = array_values($groupCounts);
}
print_r($counts);
Array
(
[1.2.3.4] => Array
(
[0] => Array
(
[0] => 1
[1] => 2
)
[1] => Array
(
[0] => 3
[1] => 4
)
)
[5.6.7.8] => Array
(
[0] => Array
(
[0] => 13
[1] => 14
[2] => 16
)
)
)