我有两个如下所示的数组:
$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中是否有一个函数可以接受字符串并查看是否存在匹配现有数组中的任何字符串?有没有人知道更高效的方法呢?
答案 0 :(得分:3)
将$arr1
映射到计算$arr2
中键的字符串编辑距离的函数,然后返回最接近的匹配。看看this Levenshtein distance功能。或者,您可以在映射函数中进行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
必须执行的操作。
最后,这不是很有效。它实际上是一个丑陋的嵌套循环。你可能会做一些修剪或其他聪明的东西,但我怀疑如果阵列相当小,你可能不在乎。
编辑:正如@Ohgodwhy在下面的评论中指出的那样,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;
}