4

我有 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');

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

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

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

“匹配”是指所有相同的元素(例如Action)或部分相同的元素(例如Test & Tes),以及那些相似但大小写不同的元素(例如Foo & fooBar &酒吧)。

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

因此,经过更多搜索后,我找到了levenshtein函数,所以我做了一个组合,首先检查精确匹配,如果没有找到,然后尝试找到最接近的匹配。现在,问题是某些列具有相似的名称,例如。Catlevel1Catlevel2,...,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 个数组之间的键引用?

4

6 回答 6

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);
?>
于 2014-08-27T05:04:48.807 回答
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 ;

?>
于 2013-06-05T13:51:55.420 回答
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]

于 2013-08-20T12:51:45.497 回答
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;
}
?>

这是完整的程序。希望能帮助到你!

于 2013-06-05T13:27:26.693 回答
0

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

祝你好运!

于 2013-05-13T14:56:11.550 回答
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; 概念是取一个数组并在循环中对其进行迭代并与第二个数组的每个值进行比较。这是为了做到这一点。

于 2013-12-17T05:51:39.717 回答