我有两个数组,看起来如下:
$arr1 = ("stringType1AndSomeRandomStuff",
"stringType2AndSomeRandomStuff",
"stringType3AndSomeRandomStuff",
"stringType1AndSomeRandomStuff",
"stringType2AndSomeRandomStuff",
"i don't belong here at all!",
"stringType4AndSomeRandomStuff");
在第一个数组($arr1
)中,大多数键都具有某种公共属性。在上面的示例文本中,这将是stringTypeX
。这个"公共因子"是我需要搜索的。每个字符串也有一些额外的数据,例如AndSomeRandomStuff
。
第二个数组如下:
$arr2 = ("stringType1" => "category1",
"stringType2" => "category2",
"stringType3" => "category3",
"stringType4" => "category4");
我需要遍历$arr1
中的每个字符串,看看它是否与$arr2
中的任何键紧密匹配。如果它与其中一个键匹配,我需要$arr2
中键的值。
如何迭代$arr1
中的每个字符串,并确定$arr2
中的键中的哪一个(如果有)适用?基本上,我需要遍历$arr1
中的每个字符串,并对$arr2
中的所有键执行部分匹配,以找到最接近的匹配。想到的直接解决方案是使用两个循环(外层用于$arr1
中的所有内容,内层用于$arr2
中的每个内容),但PHP中是否有一个函数可以获取字符串,并查看它是否与现有数组中的任何字符串匹配?有人知道有什么更具表演性的方法吗?
将$arr1
映射到一个函数,该函数计算到$arr2
中键的字符串编辑距离,然后返回最接近的匹配项。看看这个Levenstein距离函数。或者,您可以简单地在映射函数中进行startsWith比较。
你可能会有这样的东西:
$stringEditDistanceThreshold = 5; // greater than this means rejected
// define the mapping function
function findClosestMatchingString($s) {
$closestDistanceThusFar = $stringEditDistanceThreshold + 1;
$closestMatchValue = null;
foreach ($arr2 as $key => $value) {
$editDistance = levenshtein($key, $s);
// exact match
if ($editDistance == 0) {
return $value;
// best match thus far, update values to compare against/return
} elseif ($editDistance < $closestDistanceThusFar) {
$closestDistanceThusFar = $editDistance;
$closestMatchValue = $value;
}
}
return $closestMatch; // possible to return null if threshold hasn't been met
}
// do the mapping
$matchingValues = array_map('findClosestMatchingString', $arr1);
您可能需要调整$stringEditDistanceThreshold
,直到您获得满意的值。或者您可以使用startsWith函数,这将大大简化findClosestMatchingString
的操作
最后,这不是很有效。它实际上是一个丑陋的嵌套循环。你可能可以做一些修剪或其他聪明的事情,但我怀疑如果数组相当小,你可能不会在意。
编辑:正如@Ohgodh为什么在下面的评论中所说,preg_grep可能会对你更好。在这种情况下,您的地图功能将如下所示:
function findFirstMatchingString($s) {
$matchingKeys = preg_grep($s, array_keys($arr2));
if (!empty($matchingKeys) {
// return the value of the first match
return $arr2[$matches[0]];
}
return null;
}