What is a better way to replace IDs in an array with their value counterpart?

走远了吗. 提交于 2019-12-11 08:48:06

问题


I have the following array that includes id:

[Key1] => 1
[Key2] => 2, 3

I would like to replace these ids by their respective name from this second array:

[0] => Array
    (
        [ID] => 1
        [Name] => Name1
    )

[1] => Array
    (
        [ID] => 2
        [Name] => Name2
    )

[2] => Array
    (
        [ID] => 3
        [Name] => Name3

The desired output:

[Key1] => Name1
[Key2] => Name2, Name3

I have the following code which works but I know this is not the right way. If anybody could let me know what would be a better way to achieve this, it would be greatly appreciated.

What my code looks like:

$var1 = explode(", ", $array1["Key1"]); // No need to explode in this example but "Key1" sometimes includes more than 1 ID
$var2 = explode(", ", $array1["Key2"]);

$array1["Key1"] = $var1 ; // This row is for the new array generated from "explode" to be a sub-array
$array1["Key2"] = $var2 ; // Same

for ($i = 0; $i < 83; $i++){
    if($array1["Key1"][0] == $array2[$i]["ID"]){
        $array1["Key1"][0] = $array2[$i]["Name"];
    }
    if($array1["Key1"][1] == $array2[$i]["ID"]){
        $array1["Key1"][1] = $array2[$i]["Name"];
    }
// (etc)
    if($array1["Key2"][0] == $array2[$i]["ID"]){
        $array1["Key2"][0] = $array2[$i]["Name"];
    }
    if($array1["Key2"][1] == $array2[$i]["ID"]){
        $array1["Key2"][1] = $array2[$i]["Name"];
    }   
// (etc)

}

$var1 = implode(", ", $array1["Key1"]);
$var2 = implode(", ", $array1["Key2"]);

$array1["Key1"] = $var1 ;
$array1["Key2"] = $var2 ;

回答1:


Just extract the ID and Name into a single-dimension and use it as search and replace parameters. We need to modify the IDs to search for and turn them into a pattern /\b$v\b/ where \b is a word boundary, so that 1 won't replace the 1 in 164 for example:

$replace = array_column($array2, 'Name', 'ID');
$search  = array_map(function($v) { return "/\b$v\b/"; }, array_keys($replace));

$array1 = preg_replace($search, $replace, $array1);



回答2:


You need to nest some loops. Here is a sample that should work:

//Processing Array
$arrayOne = array(
    "Key1"  =>  "1",
    "Key2"  =>  "2, 3");

//Lookup Array
$arrayTwo = array(
    array(
        "ID" => "1", 
        "Name" => "Name1"),
    array(
        "ID" => "2", 
        "Name" => "Name2"),
    array(
        "ID" => "3", 
        "Name" => "Name3"));

var_dump($arrayOne);

//Loop through all values in our original array
foreach($arrayOne as &$arrValue) {
    //Split the value in the original array into another temporary array 
    //if there are multiple values.
    $valueArray = explode(", ", $arrValue);
    $outputArray = array();
    foreach($valueArray as &$myValue) {
        //Now do a lookup to replace each value
        foreach($arrayTwo as &$lookupValue) {
            //Find a match
            if($myValue==$lookupValue["ID"]) {
                $myValue = $lookupValue["Name"];
                //We found the value we want, so let's break out of this loop
                break;
            }
        }
        //Append the value
        array_push($outputArray, $myValue);
    }
    //Convert back to string
    $arrValue= implode(", ", $outputArray);
}

var_dump($arrayOne);

There are improvements you could possibly make to this code if your incoming data was always sorted, but I imagine that is just the case for your sample above.




回答3:


I have an approach to do this. You can make a try if you wish see here at:- https://eval.in/839823. I am using array_column to map the key=>value pair and then simple used foreach.

<?php
$main = ['Key1' => 1,'Key2' => '2, 3'];

$match = [
    [
        'ID' => 1,
        'Name' => 'Name1'
    ],

    [
        'ID' => 2,
        'Name' => 'Name2'
    ],
    [
        'ID' => 3,
        'Name' => 'Name3'
    ]
 ];

$final_array=[];
$mapped = array_column($match, 'Name', 'ID');
foreach($main as $k=>$v){
   $r = explode(',',$v);
    if(count($r)>1){
       $final_array[$k] = $mapped[$r[0]]. ", ".$mapped[intval($r[1])];
    }else{
       $final_array[$k] = $mapped[$r[0]];
    }
}    
print '<pre>';
//print_r($mapped);
print_r($final_array);
print '</pre>';

Output :

Array
(
    [Key1] => Name1
    [Key2] => Name2,Name3
)

Edit : As per comment of Josh Maag,

My code will only work if he only has a maximum of 2 values in Key2. If Key3 contains "4,5,6" this code will leave the 6 untouched.

<?php


 $main = ['Key1' => 1,'Key2' => '2,3','Key3' => '4,5,6'];

    $match = [
        [
            'ID' => 1,
            'Name' => 'Name1'
        ],

        [
            'ID' => 2,
            'Name' => 'Name2'
        ],
        [
            'ID' => 3,
            'Name' => 'Name3'
        ],
        [
            'ID' => 4,
            'Name' => 'Name4'
        ],
        [
            'ID' => 5,
            'Name' => 'Name5'
        ],
        [
            'ID' => 6,
            'Name' => 'Name6'
        ]
     ];

    $final_array=[];
    $mapped = array_column($match, 'Name', 'ID');
    foreach($main as $k=>$v){
       $r = explode(',',$v);
        if(count($r)>1){
           $final_array[$k] =  implode(',',array_map(function($key) use ($mapped){ return $mapped[$key]; }, array_values($r)));
        }else{
           $final_array[$k] = $mapped[$r[0]];
        }
    }    

    print '<pre>';
    print_r($mapped);
    print_r($final_array);
    print '</pre>';
    ?>

See demo See here https://eval.in/839939




回答4:


The core function that should be used for this task is preg_replace_callback(). Why? Because it is uniquely qualified to handle this operation in a single function call. It seems a tragedy to not use php functions for their designed purpose.

Beyond preg_replace_callback(), only array_column() is needed to prepare the $array2 data as a simple lookup array.

Code: (Demo)

$array1=["Key1"=>"1","Key2"=>"22, 4, 123"];
$array2=[["ID"=>"1","Name"=>"Name1"],["ID"=>"22","Name"=>"Name22"],["ID"=>"123","Name"=>"Name123"]];
$lookup=array_column($array2,'Name','ID');  // generate array: keys = IDs, vals = Names

$result=preg_replace_callback('/\d+/',function($m)use($lookup){return isset($lookup[$m[0]])?$lookup[$m[0]]:"*{$m[0]}*";},$array1);
var_export($result);

Output:

array (
  'Key1' => 'Name1',
  'Key2' => 'Name22, **4**, Name123',
)

There is no need to run any preparations (excluding $lookup) using additional loops or function calls.

This pattern will match all full ID numbers from each element in $array1 and process them individual. Each numeric match is sent to the anonymous callback function to receive its customized replacement string -- delivered by the $lookup data.

As an additional consideration, I have included an asterisk-wrapped replacement when an ID is not found in $lookup.



来源:https://stackoverflow.com/questions/45420274/what-is-a-better-way-to-replace-ids-in-an-array-with-their-value-counterpart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!