比较数组并搜索匹配值

时间:2013-05-09 14:03:10

标签: php arrays

我有2个数组,$arr1$arr2

$arr1是我希望从excel文件中读取的列的列表,$arr2是实际找到的列数组。

有时上传的文件包含

  • 拼写错误的列名称
  • 不同顺序的列
  • 可能会遗漏一些列
  • 此外,列名可能包含不同字符集中的字母(例如,希腊语'M'看起来像拉丁语 M 但不能被视为相同)。

让我们说,例如,我们有以下2个数组:

$arr1 = array('Action', 'LotSize', 'QuantityMinimum', 'SupplierName', 'SPN',
 'PartNumExt', 'UOM', 'ListPrice', 'MPN', 'MFrName', 'CatLevel1', 'CatLevel2',
 'CatLevel3', 'CatLevel4', 'CatLevel5', 'CatLevel6', 'AcctLevel1', 'AcctLevel2', 
 'AcctLevel3', 'AcctLevel4', 'AcctLevel5', 'AcctLevel6', 'Desc1', 'Desc2', 'PicName',
 'SupplierURL', 'CatPart','TechSpec', 'Kad');    

$arr2 = array('Action', 'LotSze', 'QuantityMinimum', 'SupplierName', 'SPN',
 'PartNumEx', 'UOM', 'ListPric', 'MPN', 'MfrName', 'CatLevel1', 'CatLevel2',
 'CatLevel3', 'CatLevel4', 'AcctLevel1', 'AcctLevel2', 'AcctLevel3', 'AcctLevel4',
 'Desc1', 'Desc2', 'PicName', 'SupplierURL', 'CatPart');

我需要比较2个数组并将匹配元素的位置保存到第3个数组:

$arr3 = ([0]=>0, [1]=>1, [2]=>3, [3]=>5, [4]=>6, [5]=>...);

$arr1中显示$arr2的每个匹配元素的位置。

“匹配”是指所有相同的元素(例如动作)或部分相同(例如测试& 测试,)以及那些相似但但情况不同的元素(例如 Foo & foo Bar & )。

我几天前发布了this question,我得到了一个很好的答案,但经过多次测试后,我发现它并不总能按预期工作。

因此,经过更多搜索,我找到了levenshtein函数,所以我做了一个首先检查完全匹配的组合,如果没有找到,则尝试找到最接近的匹配。现在,问题是某些列具有相似的名称,例如。 Catlevel1 Catlevel2 ,..., Catlevel6 。因此,如果缺少 Catlevel2 ,它将与最后一个&最相似的列 Catlevel6

这是我到目前为止所做的:

foreach($all_columns as $i => $val1) {
    $result = null;
    // Search the second array for an exact match, if found
    if(($found = array_search($val1,$_SESSION['found_columns'],true)) !==false) {
        $result = $found; 
    } else {
        // Otherwise, see if we can find a case-insensitive matching string 
        //where the element from $arr2 is found within the one from $arr1
        foreach( $_SESSION['found_columns'] as $j => $val2) {
            if($val1<>'' && $val2<>'') {
                if( stripos( $val1, $val2) !== false ) {
                    $result = $j;
                    break;
                } else {
                    $notfound .= $val1.', ';
                    break;
                }
            }
        }
    }
    $_SESSION['found_column_positions'][$i] = $result;
}

/*****ALTERNATIVE METHOD USING levenshtein*****/
$i=0;
foreach($all_columns as $key => $value) {
    $found = wordMatch($value, $arr2, 2);
    $pos = array_search($found, $_SESSION['found_columns']); 
    $_SESSION['found_column_positions'][$i] = $pos;
    $i++;
}

function wordMatch($input, $array, $sensitivity){
    $words = $array;
    $shortest = -1;
    foreach ($words as $word) {
        $lev = levenshtein($input, $word);
        if ($lev == 0) {
            $closest = $word;
            $shortest = 0;
            break;
        }
        if ($lev <= $shortest || $shortest < 0) {
            $closest  = $word;
            $shortest = $lev;
        }
    }
    if($shortest <= $sensitivity){
        return $closest;
    } else {
        return 0;
    }
}

<小时/> 是否有更好的方法来比较2个数组,找到最接近的值匹配并将匹配值键保存到第3个数组以用作2个数组之间的关键引用?

6 个答案:

答案 0 :(得分:1)

以下脚本将完成工作。

<?php
$arr1 = array('Action', 'LotSize', 'QuantityMinimum', 'SupplierName', 'SPN',
 'PartNumExt', 'UOM', 'ListPrice', 'MPN', 'MFrName', 'CatLevel1', 'CatLevel2',
 'CatLevel3', 'CatLevel4', 'CatLevel5', 'CatLevel6', 'AcctLevel1', 'AcctLevel2', 
 'AcctLevel3', 'AcctLevel4', 'AcctLevel5', 'AcctLevel6', 'Desc1', 'Desc2', 'PicName',
 'SupplierURL', 'CatPart','TechSpec', 'Kad');    

$arr2 = array('Action', 'LotSze', 'QuantityMinimum', 'SupplierName', 'SPN',
 'PartNumEx', 'UOM', 'ListPric', 'MPN', 'MfrName', 'CatLevel1', 'CatLevel2',
 'CatLevel3', 'CatLevel4', 'AcctLevel1', 'AcctLevel2', 'AcctLevel3', 'AcctLevel4',
 'Desc1', 'Desc2', 'PicName', 'SupplierURL', 'CatPart');

$arr3 = array();

foreach($arr1 as $key=>$val)
{
    $arr3[$key] = array_search($val, $arr2);
}

print_r($arr3);
?>

答案 1 :(得分:0)

我不确定这是否适合您,但我们有一个类似的系统,用户管理页面告诉我们每个标头的可能值。然后,在尝试上载之前,系统会转换为标准接受的标头。基于用户创建的映射。这避免了强制用户每次映射。如果他们尝试上传的其中一列没有条目,则上传会引发错误。

祝你好运!

答案 2 :(得分:0)

<?php
$arr1 = array('Action', 'LotSize', 'QuantityMinimum', 'SupplierName', 'SPN',
'PartNumExt', 'UOM', 'ListPrice', 'MPN', 'MFrName', 'CatLevel1', 'CatLevel2',
'CatLevel3', 'CatLevel4', 'CatLevel5', 'CatLevel6', 'AcctLevel1', 'AcctLevel2', 
'AcctLevel3', 'AcctLevel4', 'AcctLevel5', 'AcctLevel6', 'Desc1', 'Desc2', 'PicName',
'SupplierURL', 'CatPart','TechSpec', 'Kad');  

$arr2 = array('Action', 'LotSze', 'QuantityMinimum', 'SupplierName', 'SPN',
'PartNumEx', 'UOM', 'ListPric', 'MPN', 'MfrName', 'CatLevel1', 'CatLevel2',
'CatLevel3', 'CatLevel4', 'AcctLevel1', 'AcctLevel2', 'AcctLevel3', 'AcctLevel4',
'Desc1', 'Desc2', 'PicName', 'SupplierURL', 'CatPart');

$arr3=array();

for($i = 0; $i < count($arr1) ;$i++)
{ 
$max=0;
$result=0;
for ($j=0; $j< count($arr2) ; $j++)
{
     $percent=find($arr1[$i],$arr2[$j]);
     if ($percent>$max) 
             { $max= $percent;
               $result=$j; 
            } 

 }
 $arr3[$i]=$result;
}
for($i = 0; $i < count($arr3) ;$i++)
    echo "[".$i."]=> ".$arr3[$i].", ";

function find($a,$b)
{
similar_text($a, $b, $percent);
return $percent;
}
?>

这是完整的计划。希望能帮助到你!

答案 3 :(得分:0)

?php
$arr1 = array('Action', 'LotSize', 'QuantityMinimum', 'SupplierName', 'SPN',
'PartNumExt', 'UOM', 'ListPrice', 'MPN', 'MFrName', 'CatLevel1', 'CatLevel2',
'CatLevel3', 'CatLevel4', 'CatLevel5', 'CatLevel6', 'AcctLevel1', 'AcctLevel2', 
'AcctLevel3', 'AcctLevel4', 'AcctLevel5', 'AcctLevel6', 'Desc1', 'Desc2', 'PicName',
'SupplierURL', 'CatPart','TechSpec', 'Kad');  

$arr2 = array('Action', 'LotSze', 'QuantityMinimum', 'SupplierName', 'SPN',
'PartNumEx', 'UOM', 'ListPric', 'MPN', 'MfrName', 'CatLevel1', 'CatLevel2',
'CatLevel3', 'CatLevel4', 'AcctLevel1', 'AcctLevel2', 'AcctLevel3', 'AcctLevel4',
'Desc1', 'Desc2', 'PicName', 'SupplierURL', 'CatPart');

$arr3 = array_intersect($arr1, $arr2));
echo arr3 ;

?>

答案 4 :(得分:0)

这是一个非常简单的算法,使用array_search()

$mapping = [];

foreach ($arr1 as $i => $value)
{
    $actualKey = array_search($value, $arr2);

    if (false !== $actualKey)
    {
        $mapping[$i] = $actualKey;
    }
}

array_search($ needle,$ haystack)

  

array_search - 在数组中搜索给定值,如果成功则返回相应的键[否则为false]

答案 5 :(得分:0)

使用内部和外部循环概念。

<pre>
$arr1 = $ar1;
$arr2 = $ar2;
$matching_vals = '';
foreach($arr1 as $array1){
$val_arr1 = $array1;
foreach($arr2 as $array2){
$val_arr2 = $array1;
if($val_arr2 == $val_arr1){
$matching_vals .= $val_arr2;
}
}
}

echo'匹配值为:'。 $ matching_vals; 概念是采用一个数组并在循环中迭代它并与第二个数组的每个值进行比较。这是算法。