Comparing arrays and finding matching values

I have 2 arrays, $arr1 and $arr2 :

$arr1 is a list of columns that I expect to read from an excel file, $arr2 is an array of columns that were actually found.

Sometimes the downloaded file contains

  • Error column names
  • Columns in a different order
  • Multiple columns may be missing
  • In addition, column names may contain letters in a different encoding (for example, the Greek "M", which looks like the Latin M, but cannot be considered the same).

Suppose, for example, that we have the following 2 arrays:

 $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'); 

I need to compare 2 arrays and save the position of the corresponding elements in the 3rd array:

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

mapping the position of each matched element of $arr1 to $arr2 .

By "matching" I mean all elements that are identical (for example, Action ) or partially the same (for example, Test and Tes ,), as well as those elements that are the same, but are in another case (for example, Foo and foo , Bar, and / strong>).

I posted this question a few days ago, and I had a good answer, but after several tests with a lot of data, I found that it does not always work properly.

So, after a larger search, I found levenshtein , so I made a combination that first checks the exact match, and if not found, then tries to find the closest match. Now the problem is that some columns have similar names, for example. Catlevel1 , Catlevel2 , ..., Catlevel6 . Therefore, if Catlevel2 is missing, it will be mapped to the last and most similar column, which is Catlevel6 .

This is what I have so far:

 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; } } 

<h / "> Is there a better way to compare 2 arrays, find the closest match and save the value matching key for the 3rd array for use as a key link between two arrays?

+4
source share
6 answers

After the script, work will be done.

 <?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
source

I'm not sure if this is an option for you or not, but we have a similar system in which users manage the page to tell us what the possible values ​​for each heading are. The system then proceeds to the standard accepted header before attempting to load. based on user generated mapping. This avoids user reconfiguration every time. If there is no entry for one of the columns that they are trying to load, loading will give an error message.

Good luck

0
source
 <?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; } ?> 

This is a complete program. Hope it helps!

0
source
 ?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 ; ?> 
0
source

Very simple algorithm: 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 - Searches for an array for the given value and returns the corresponding key if it is successful [false otherwise]

0
source

To do this, use the concept of the inner and outer loop.

 <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 'Relevant values:'. $ matching_vals; The concept is to take one array and iterate over it in a loop and compare with each value of the second array. This is algo for this.

0
source

Source: https://habr.com/ru/post/1479924/


All Articles