Inject an array inbetween another array in PHP - php

I have to merge (inject) an array in between another array.
Injected array is adding an additional level at the top.
Actual code is different, but here I have created a simple example to illustrate the issue I am facing.
Here is the sample code:
$mid_array = [
'heading3' => 'Heading 3',
'heading4' => 'Heading 4'
];
$main_array = [
'heading1' => 'Heading 1',
'heading2' => 'Heading 2',
$mid_array,
'heading5' => 'Heading 5'
];
echo '<pre>'; print_r($main_array); echo '</pre>';
Output I am getting
Array
(
[heading1] => Heading 1
[heading2] => Heading 2
[0] => Array
(
[heading3] => Heading 3
[heading4] => Heading 4
)
[heading5] => Heading 5
)
This is what exactly I need
Array
(
[heading1] => Heading 1
[heading2] => Heading 2
[heading3] => Heading 3
[heading4] => Heading 4
[heading5] => Heading 5
)

Based on the assumption that your arrays might change but will continue to have keys like heading1, heading2 this would be my solution
$newArray = array_merge($main_array,$mid_array);
ksort($newArray);
this will return the array you need.

I think you are looking for array_splice, as such:
array_splice($main_array, 2, 0, $mid_array);
Note: array_splice does not preserve keys, if keys are important to you, use following:
function array_insert(&$input, array $arrayToAdd, int $atPosition) {
$before = array_slice($input, 0, $atPosition, true);
$after = array_slice($input, $atPosition, null, true);
$input = $before + $arrayToAdd + $after;
}
Usage
array_insert($main_array, $mid_array, 2);

I think you are looking for the array_merge functionality.
http://php.net/manual/en/function.array-merge.php

You can use array_reduce:
$after = 'heading2';
$result = array_reduce(
array_keys($main_array),
function ($carry, $key) use ($main_array, $after, $mid_array) {
$carry[$key] = $main_array[$key];
return $key === $after
? array_merge($carry, $mid_array)
: $carry;
},
[]
);
Here is the demo.

If key ordering presents a problem (with something like array_merge) you can flatten the inserted array by walking it recursively. You walk along the tips plucking what you need as you go.
<?php
$insert = [
'foo' => 'And it\'s been the ruin of many a poor boy',
'bar' => 'And god I know I\'m one'
];
$inserted = [
'big' => 'There is a house in New Orleans',
'fat' => 'They call the rising sun',
$insert,
'mama' => 'My mother was a taylor'
];
$flattened = [];
array_walk_recursive(
$inserted,
function($v, $k) use (&$flattened) {
$flattened[$k] = $v;
}
);
var_export($flattened);
Output:
array (
'big' => 'There is a house in New Orleans',
'fat' => 'They call the rising sun',
'foo' => 'And it\'s been the ruin of many a poor boy',
'bar' => 'And god I know I\'m one',
'mama' => 'My mother was a taylor',
)

Related

How to convert normal array into an associative array using php

i have a string this one: position1, position2
Basically i want to have this kind of structure -
array(
array('position' => 'position 1'),
array('position' => 'position 2')
)
i have tried this so far.
$positions = explode(',', "position1, position2");
$modPoses = [];
foreach($positions as $pose):
$modPoses['position'] = $pose;
endforeach;
print_r($modPoses);
Output:
Array ( [position] => position2 )
How can i get desired(mentioned above) array structure?
Thank you.
I guess that what You want is:
array(
array('position' => 'position 1'),
array('position' => 'position 2')
)
If that is so, You can use:
array_map(function ($i) { return array('position' => $i); }, explode(',', 'position 1, position 2'))
It does not make any sense that you assign two values to same index but let me give you a solution. If you use 2d associative array then you can do it in this way
$counter = 0; //initialize counter here
foreach($positions as $pose):
$modPoses[$counter]['position'] = $pose;
$counter++;
endforeach;

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

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 ;
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);
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.
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
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.

Populate multidimensional array with data

While renown scientists are looking into other dimensions I'm trying to figure out how to populate multidimensional arrays with dynamic data.
I need to add an undetermined number of values that are calculated from a random function.
function my_random ($min, $max) {
$random_var = rand($min, $max);
return $random_var;
}
I would like my array to look like this:
$array_example = [
'id' => $id,
'value1' => $value1,
'value2' => $value2
];
...or maybe like this:
$array[$i] = [
'id' => $id, array(
'value1' => $value1,
'value2' => $value2
)
];
I figured a simple for-loop would do the trick and so I tried this:
for ($i = 1; $i <= $amount; $i++) {
$array[$i] = $i;
$array[$i] = [
'id' => $i, array(
'value1' => $value1,
'value2' => $value2
)
];
}
...but it comes out all wrong (from console):
string(103) "{"id":2,"value1":[14,{"1":{"id":1,"0":{"value1":[14],"value2":[11]}}},13],"value2":[11,19]}"
The for-loop seems to nest them. I tried different functions, hoping to get it right: range() to get the id and then populate it with data, array_push() and I even tried to combine and merge.
This thread makes it look simple:
$array[] = "item";
$array[$key] = "item";
array_push($array, "item", "another item");
But this solution will only work to create the index.
How do I insert those values into each index dynamically? What I ultimately need is to be able to access the array and its values like this:
$array[0]["value1"].
Thanks.
Indexed array of associative arrays
An array in PHP is actually an ordered map. A map is a type that associates values to keys. This type is optimized for several different uses; it can be treated as an array, list (vector), hash table (an implementation of a map), dictionary, collection, stack, queue, and probably more. As array values can be other arrays, trees and multidimensional arrays are also possible.
The following function takes one optional integer argument, or defaults to 10, and initiates a for loop to create an indexed Array of associative array()s.
<!DOCTYPE html><html><head></head><body>
<?php
function createArrayOf( $quantity = 10 ) {
$arr = [];
for ( $i = 0; $i < $quantity; ++$i ) {
$arr[ $i ] = array(
"value_1" => "some value",
"value_2" => "another value"
);
}
return $arr;
}
?>
<pre><?php var_export( createArrayOf( 5 ) ); ?></pre>
</body></html>
Output using var_export() which:
gets structured information about the given variable. It is similar to var_dump() with one exception: the returned representation is valid PHP code.
array (
0 =>
array (
'value_1' => 'some value',
'value_2' => 'another value',
),
1 =>
array (
'value_1' => 'some value',
'value_2' => 'another value',
),
2 =>
array (
'value_1' => 'some value',
'value_2' => 'another value',
),
3 =>
array (
'value_1' => 'some value',
'value_2' => 'another value',
),
4 =>
array (
'value_1' => 'some value',
'value_2' => 'another value',
),
)

how to get multi-dimensional array data with another one-dimension array

What I'd like to do is have a function that accepts two arguments, both arrays, the first being a one-dimensional array of varying lengths and the second is a multi-dimensional array of varying depths and lengths. The first array is never associative, the second is always a fully associative array.
This function would return the requested value from the multi-dimensional array as indicated by the first array.
Assume that the first array will always be hand-written and passed to this function. Meaning the developer always knows there is a value to be returned from the multi-dimensional array and would never pass a request to the function where a value did not exist.
I think the code below is the best example at what I'm trying to achieve.
//Example multi-dimensional array
$multi = array(
'fruit' => array(
'red' => array(
'strawberries' => '$2.99/lb',
'apples' => '$1.99/lb'
),
'green' => array(
'honeydew' => '$3.39/lb',
'limes' => '$0.75/lb'
)
),
'vegetables' => array(
'yellow' => array(
'squash' => '$1.29/lb',
'bellpepper' => '$0.99/lb'
),
'purple' => array(
'eggplant' => '$2.39/lb'
)
),
'weeklypromo' => '15% off',
'subscribers' => array(
'user1#email.com' => 'User 1',
'user2#email.com' => 'User 2',
'user3#email.com' => 'User 3',
'user4#email.com' => 'User 4'
)
);
//Example one-dimensional array
$single = array('fruit', 'red', 'apples');
function magicfunc($single, $multi) {
//some magic here that looks something like below
$magic_value = $multi[$single[0]][$single[1]][$single[2]];
return $magic_value;
}
//Examples:
print magicfunc(array('fruit', 'red', 'apples'), $multi);
Output:
$1.99/lb
print magicfunc(array('subscribers', 'user3#email.com'), $multi);
Output:
User 3
print magicfunc(array('weeklypromo'), $multi);
Output:
15% off
This returns the values as requested:
function magicfunc($single, $multi) {
while (true) {
if (!$single) {
break;
}
$searchIndex = array_shift($single);
foreach ($multi as $k => $val) {
if ($k == $searchIndex) {
$multi = $val;
continue 2;
}
}
}
return $multi;
}

Get path and value of all elements in nested associative array

Consider an associative array of arbitrary form and nesting depth, for example:
$someVar = array(
'name' => 'Dotan',
'age' => 35,
'children' => array(
0 => array(
'name' => 'Meirav',
'age' => 6,
),
1 => array(
'name' => 'Maayan',
'age' => 4,
)
),
'dogs' => array('Gili', 'Gipsy')
);
I would like to convert this to an associative array of paths and values:
$someVar = array(
'name' => 'Dotan',
'age' => 35,
'children/0/name' => 'Meirav',
'children/0/age' => 6,
'children/1/name' => 'Maayan',
'children/1/age' => 4,
'dogs/0' => 'Gili',
'dogs/1' => 'Gipsy'
);
I began writing a recursive function which for array elements would recurse and for non-array elements (int, floats, bools, and strings) return an array $return['path'] and $return['value']. This got sloppy quick! Is there a better way to do this in PHP? I would assume that callables and objects would not be passed in the array, though any solution which deals with that possibility would be best. Also, I am assuming that the input array would not have the / character in an element name, but accounting for that might be prudent! Note that the input array could be nested as deep as 8 or more levels deep!
Recursion is really the only way you'll be able to handle this, but here's a simple version to start with:
function nested_values($array, $path=""){
$output = array();
foreach($array as $key => $value) {
if(is_array($value)) {
$output = array_merge($output, nested_values($value, (!empty($path)) ? $path.$key."/" : $key."/"));
}
else $output[$path.$key] = $value;
}
return $output;
}
function getRecursive($path, $node) {
if (is_array($node)) {
$ret = '';
foreach($node as $key => $val)
$ret .= getRecursive($path.'.'.$key, $val);
return $ret;
}
return $path.' => '.$node."\n";
}
$r = getRecursive('', $someVar);
print_r($r);
All yours to place it in an array.

Categories