I have this array:
$data = [
["id" => 1, "data" => "data 1"],
["id" => 2, "data" => "data <4>"],
["id" => 3, "data" => "data 3"],
["id" => 4, "data" => "<3>"]
];
I want to produce a new array. The resulting array should be:
[
["id" => 1, "data" => "data 1"],
["id" => 2, "data" => "data data 3"],
["id" => 3, "data" => "data 3"],
["id" => 4, "data" => "data 3"]
]
The idea is that each time there is <number>
in the data
attribute then this value should be replaced by the data
attribute in the element which has the same id
. In the example above, the last element is: ["id" => 4, "data" => "<3>"]
So we replace <3>
with data 3
since it is what is stored in the data
attribute of element with id => 3
.
I have already created a function that works with the above array:
public function refProcess($data, &$newData, $i, &$tmpData){
$dataLength = count($data);
if($i>=$dataLength){
return;
}
for(;$i<$dataLength;$i++){
if(is_null($tmpData)){
$tmpData = ['id'=> $data[$i]['id'], 'data'=>null];
}
if(strpos($data[$i]['data'],"[")!==false){
$parsed = $this->getInbetweenStrings("<", ">", $data[$i]['data']);
if(count($parsed)){
foreach($parsed as $occurance){
foreach($data as $key => $dataValue){
if($dataValue['id']==$occurance){
if(strpos($dataValue['data'], "<")!==false){
$this->refProcess($data, $newData, $key, $tmpData);
$tmpData=null;
}
else{
$tmpDataAtt = str_replace("<".$occurance.">", $dataValue['data'], $data[$i]['data']);
$tmpData['data'] = $tmpDataAtt;
$newData [] = $tmpData;
$tmpData = null;
break;
}
}
}
}
}
}
else{
$tmpData['data'] = $data[$i]['data'];
$newData [] = $tmpData;
$tmpData = null;
}
}//foreach
}
//returns an array contains strings existing between $start and $end. Multiple occurance
public function getInbetweenStrings($start, $end, $str){
$matches = array();
$regex = "/$start([a-zA-Z0-9_]*)$end/";
preg_match_all($regex, $str, $matches);
return $matches[1];
}
It works fine until I add another element to the array:
$data = [
["id" => 1, "data" => "data 1"],
["id" => 2, "data" => "data <4>"],
["id" => 3, "data" => "data 3"],
["id" => 4, "data" => "<3>"]
["id" => 5, "data" => "<2>"]
];
Element with id:5
the function goes into an endless loop. What am I missing?
The code can be tested at https://onlinephp.io/c/0da5d
4
Answers
You dont really do any recursive stuff, is a quit flat array structure you have.
UPDATE: This was wrong, keep it just for the related comments:
UPDATE:
Here is now a working solution.
UPDATED:
Your code is way too complicated, there’s an easier approach. Note, I reindex the initial data to the key:id -> value:array, to avoid all those loops for finding the entry for required id.
If there may be two entries with the same id, this approach not gonna work.
Your code is too clumsy to begin with. I would rather suggest a much simpler approach.
Index your array with
id
value as it’s key witharray_column
. This way, we can access any index withid
of a particular value in O(1) time. This also gives you an advantage for the value of theid
to be anything and not necessarily being symmetric with your subarray index key.Capture the ID using regex. If there is a match, recurse again, else, our search ends here. Return it’s
data
value to the parent call and you are done.Snippet:
Online Demo
Here is a tidy recursive snippet that will modify your array by reference.
Loop over the array (I am choosing to use array de-structuring syntax to declare individual row variables.
If the needle is null or matches the row id, attempt the recursive replacement.
If the needle matches a row’s id, return the value to the parent level, so that eventually the top level array is affected.
Code: (Demo)