How to synchronously nest subarrays from one array into subarrays of another? - php

I have 2 multi-dimensional arrays:
$category = array (
37 = array (id=1, name=joe, boss=kev)
73 = array (id=55, name=diane, boss=rox)
11 = array (id=4, name=bideo, boss=julia)
)
$other_variable = array (
1 = array (
picture1 = array (name=zee, id=4),
picture2 = array (name=izzy, id=1)
)
2 = array (
picture1 = array (name=foo, id=55),
picture2 = array (name=ido, id=44)
)
3 = array (
picture1 = array (name=wheez, id=87),
picture2 = array (name=ardu, id=9)
)
)
I want to combine them so that
$category = array (
37 = array (
id=1,
name=joe,
boss=kev,
other_variable = array (
picture1 = array (name=zee, id=4),
picture2 = array (name=izzy, id=1)
),
73 = array (
id=55,
name=diane,
boss=rox,
other_variable = array (
picture1 = array (name=foo, id=55),
picture2 = array (name=ido, id=44)
),
11 = array (
id=4,
name=bideo,
boss=julia,
other_variable = array (
picture1 = array (name=wheez, id=87),
picture2 = array (name=ardu, id=9)
)
)
I have tried
$new_array = array_map(null, $category, $other_variable);
That combines the two arrays, but it creates several nested levels in the array. I am looking for something much cleaner that maintains $category as the parent array.

Are you expecting something like this? Here we are using next and current function for incrementing internal pointer of array and getting current value.
Try this code snippet here
foreach($category as &$value)
{
$value["other_variable"]=current($other_variable);
next($other_variable);
}
print_r($category);

You were kind of on the right path with your use of array_map() to synchronously iterate two arrays, but sadly that function is going to kill your first level keys.
From the array_map() manual:
The returned array will preserve the keys of the array argument if and only if exactly one array is passed. If more than one array is passed, the returned array will have sequential integer keys.
array_walk() is going to be a cleaner / more appropriate function call for your task of modifying the $category array. array_walk() allows you to modify your $category array and synchronously iterate your $other_variable array (as the optional userdata parameter) without any additional iterated function calls (e.g. next()).
Code: (Demo)
$category=[
37=>["id"=>1,"name"=>"joe","boss"=>"kev"],
73=>["id"=>55,"name"=>"diane","boss"=>"rox"],
11=>["id"=>4,"name"=>"bideo","boss"=>"julia"]
];
$other_variable=[
1=>["picture1"=>["name"=>"zee","id"=>4],"picture2"=>["name"=>"izzy","id"=>1]],
2=>["picture1"=>["name"=>"foo","id"=>55],"picture2"=>["name"=>"ido","id"=>44]],
3=>["picture1"=>["name"=>"wheez","id"=>87],"picture2"=>["name"=>"ardu","id"=>9]]
];
array_walk($category,function(&$v,$k,$ov){$v['other_variable']=current($ov);},$other_variable);
var_export($category);
Output:
array (
37 =>
array (
'id' => 1,
'name' => 'joe',
'boss' => 'kev',
'other_variable' =>
array (
'picture1' =>
array (
'name' => 'zee',
'id' => 4,
),
'picture2' =>
array (
'name' => 'izzy',
'id' => 1,
),
),
),
73 =>
array (
'id' => 55,
'name' => 'diane',
'boss' => 'rox',
'other_variable' =>
array (
'picture1' =>
array (
'name' => 'zee',
'id' => 4,
),
'picture2' =>
array (
'name' => 'izzy',
'id' => 1,
),
),
),
11 =>
array (
'id' => 4,
'name' => 'bideo',
'boss' => 'julia',
'other_variable' =>
array (
'picture1' =>
array (
'name' => 'zee',
'id' => 4,
),
'picture2' =>
array (
'name' => 'izzy',
'id' => 1,
),
),
),
)
Late Edit:
Additional methods that modify the $other_variable array (effectively empty it when the iterative process resolves) include:
$category=array_map(function($v)use(&$other_variable){
return $v+=['other_variable'=>array_shift($other_variable)];
},$category);
and
foreach($category as &$value){
$value["other_variable"]=array_shift($other_variable);
}
Obviously, these methods should only be used if you do not intend to use $other_variable down script or you are going to declare a copy of the array for later use.

Related

Flatten a multi-dimensional array, whilst removing an element from each

Is it possible to flatten a multi-dimensional array, whilst also removing an element from each sub-array?
Currently, I am storing two elements per sub-array, like so:
Array (
[billing_first_name] => Array (
[0] => Test
[1] => 1
)
[billing_last_name] => Array (
[0] => Test
[1] => 1
)
)
But I need to remove the second sub-element, flattening the array to:
Array (
[billing_first_name] => Test
[billing_last_name] => Test
)
I had thought that this could be possible through a foreach, but after removing the 2nd element from the sub-array, I'm unsure what route would be most efficient to flatten the array.
foreach( $customer_data_new as $key => $value ) {
unset($customer_data_new[$key][1]);
}
If anyone could explain the best option, I would be graatful.
Can you try the below code
$customer_data_new = array(
'billing_first_name' => array(
'0' =>'Test',
'1' => 1
),
'billing_last_name' => array(
'0' =>'Test',
'1' => 1
)
);
$newData = array();
foreach( $customer_data_new as $key => $value ) {
$newData[$key] = $value[0];
}
print_r($newData);
Demo Link
Call current() on every subarray. Dead simple.
Code: (Demo)
var_export(array_map('current', $customer_data_new));
Output:
array (
'billing_first_name' => 'Test',
'billing_last_name' => 'Test',
)

convert more arrays into single array

Convert these array into one array
Array ( [0] => 10 )
Array ( [0] => 17 )
Array ( [0] => 17 )
Array ( [0] => 15 )
I want an output like this:
Array ( [0] => 10 ,[1] => 17,[2] => 17,[3] => 15)
$a=array(10);$b=array(17);$c=array(17);$d=array(15);
print_r(array_merge($a,$b,$c,$d));
//Array([0]=>10 [1]=>17 [2]=>17 [3]=>15)
Assuming that your Main Array contains some sub-arrays nested within it like so:
<?php
$arrNestedArray = array(
array(10),
array(17),
array(17),
array(15),
array("data"=>array("fName"=>"Cosmic", "lName"=>"Joy")),
);
And, now; you want to take-out all the values of every element in the sub-arrays and turn them into direct elements of the Main Array. You can do that with array_walk... and then build up your Flat Array having the Structure you had anticipated like this:
<?php
// CREATE AN EMPTY ARRAY TO HOLD THE FINAL RESULT YOU DESIRED...
$singleArray = array();
// THIS IS A SAMPLE OF THE MAIN ARRAY CONTAINING SUB ARRAYS...
$arrNestedArray = array(
array(10),
array(17),
array(17),
array(15),
array("data"=>array("fName"=>"Cosmic", "lName"=>"Joy")),
);
array_walk($arrNestedArray, function($data, $index) use(&$singleArray) {
if( is_array($data) ) {
foreach ($data as $key=>$item) {
if(!in_array($item, $singleArray)) {
if(is_array($item)) {
$singleArray[$key] = $item;
}else{
$singleArray[$index] = $item;
}
}
}
}
});
var_dump($singleArray);
Finally, while you might still want to test it out here; the var_dump above produces something like this:
array (size=4)
0 => int 10
1 => int 17
3 => int 15
'data' =>
array (size=2)
'fName' => string 'Cosmic' (length=6)
'lName' => string 'Joy' (length=3)
Use array_merge with call_user_func_array:
$a = array(Array ( 0 => 10 ), Array ( 0 => 17 ), Array ( 0 => 17 ), Array ( 0 => 15 ));
$ra = call_user_func_array('array_merge', $a);
print_r($ra); // Array ( [0] => 10 [1] => 17 [2] => 17 [3] => 15 )

php merge multidimensional arrays into each other

I have two multidimensional arrays in php and want to merge them.
First one :
array1 = (
0 => array (
0 => array(
id => 1,
name => "test"
)
)
1 => array(...)
)
Second one :
array2 = (
0 => array (
0 => array(
id => 200,
name => "test"
),
1 => array(
id => 201,
name => "test"
)
)
1 => array(...)
)
And the merged array must be like this :
lastArray = (
0 => array (
0 => array(
id =>1,
name => "test"
),
1 => array(
id => 200,
name => "test"
),
2 => array (
id => 201,
name => "test"
)
)
1 => array(...)
)
How should I do this with a proper foreach loop?
According to the lastArray that you've presented - you need to merge the inner arrays only at 0 position/index(and you didn't show how should look a merge result at 1 index).Use the following approach:
$array1[0] = array_merge($array1[0], $array2[0]);
// now, $array1 is your $lastArray
Method 1:
Why not use array_merge or array-merge-recursive for this? This will merge the both (or more) arrays.
$array = array_merge($array1, $array2);
$array = array_merge-recursive($array1, $array2);
Method 2:
Loop through one array.
(You may check if the key is equal to the others array key).
Maybe something like this:
foreach($array_1 as $key=>$value) $array_2[$key] = $value;
Reminder from splash58: Don't forget to use usort in both methods to sort the array by values after sort by id

Get intersection of a multi-dimensional array in PHP

Starting Point
I have a multi-dimensional array, like the follow example:
$array = array (
'role_1' =>
array (
0 => 'value_2',
1 => 'value_3',
),
'role_2' =>
array (
0 => 'value_1',
1 => 'value_2',
),
'role_3' =>
array (
0 => 'value_2',
1 => 'value_3',
),
)
Goal
I like to loop about the sub-arrays to get only the intersection. The array was created dynamically, can have a lot of sub-arrays role_[x] and also a lot of key/value inside the sub-arrays. The key is not necessary, only the value. The key is also a count, not a string.
As result I like to get in this example this small array.
$array = array( 'value_2' )
The index, "the array-name", like role_1 of the sub-arrays is not more relevant after intersection. Important for me in the result is the values, only the values there are existed in each sub-array.
Try
I had tried with the source, but I think it is possible much simpler.
$value_stack = array();
$result = array();
$i = 0;
foreach( $settings_ as $role => $values ) {
foreach( $values as $value ){
if( in_array( $value,$value_stack ) || $i === 0 ) {
$result[ $role ][] = $value;
}
$value_stack[] = $value;
}
$i++;
};
The merge of this multi array result should run with a array_merge in a loop.
Thanks for your time.
You can use array_intersect to cover the dynamic $data as such:
$data = array (
'role_1' =>
array (
0 => 'value_2',
1 => 'value_3',
),
'role_2' =>
array (
0 => 'value_1',
1 => 'value_2',
),
'role_3' =>
array (
0 => 'value_2',
1 => 'value_3',
)
);
$result = call_user_func_array('array_intersect', $data);
call_user_func_array will help spread the elements of your array as parameters inside array_intersect.
You should be able to do
call_user_func_array('array_intersect', $array_of_arrays)
This will pass each element of your array of arrays as an argument to array_intersect, which takes a variable number of arrays as arguments and returns their intersection.
array_intersect work for this:
$data = array (
'role_1' =>
array (
0 => 'value_2',
1 => 'value_3',
),
'role_2' =>
array (
0 => 'value_1',
1 => 'value_2',
),
'role_3' =>
array (
0 => 'value_2',
1 => 'value_3',
)
);
$result = array_intersect($data['role_1'], $data['role_2'], $data['role_3']);
print_r($result);
result :
Array ( [0] => value_2 )
As of PHP 5.6+ the splat/spread operator can be used to unpack the arguments in a call to array_intersect(). In order to remove the non-numeric keys from the array, pass $array to a call to array_values().
$result = array_intersect(...array_values($array));
See a demonstration in this playground example.

Moving multidimensional array items

So i have this array:
$input = array (
1 => array (
'TitleName' => 'Details',
'TitleID' => 1,
1 => array (
'ID' => 1,
'Name' => 'First Name'
),
2 => array (
'ID' => 2,
'Name' => 'Last Name'
),
3 => array (
'ID' => 4,
'Name' => 'City')
),
12 => array (
'TitleName' => 'System',
'TitleID' => 12,
0 => array (
'ID' => 3,
'Name' => 'Cpu'
)
)
);
And i have an Array that tells me how to order the array above:
$order = array
(
1 => array(
0 => 1, // this is the ID in the third dimension
1 => 4,
2 => 2,
),
12 => array (
0 => 3
)
);
So the point is that i will get in my final array :
Array
(
[1] => Array
(
[TitleName] => Details
[TitleID] => 1
[1] => Array
(
[ID] => 1
[Name] => First Name
)
[2] => Array
(
[ID] => 4
[Name] => City
)
[3] => Array
(
[ID] => 2
[Name] => Last Name
)
)
[12] => Array
(
[TitleName] => System
[TitleID] => 12
[0] => Array
(
[ID] => 3
[Name] => Cpu
)
)
)
Also, how can i move items inside the array to different parent?
I've tried this code, but no luck.
usort($array, function ($a, $b) use ($order) {
$pos_a = array_search($a['id'], $order);
$pos_b = array_search($b['id'], $order);
return $pos_a - $pos_b;
});
Any ideas?? Thanks!
Since your id's are unique, it might be easier to just fill two temporary arrays and then iterate over the ordering array to create your desired output.
Here's a possible solution. No need for array_search here.
Having your two goven arrays, we'll first iterate over the input, seperating the common 1st level elements and it's attributes and the children elements.
To distinguish between attributes of first level elements and chiuldren we use is_numeric on the key (since attribute keys are not numeric) and is_array (just to be sure).
// our temporary arrays
$tmpElements = array();
$tmpChildren = array();
// iterate over array
foreach($input as $key => $value) {
$tmpElementAttributes = array(); // init/reset the temporary attributes array
// iterate over children and attributes
foreach ($value as $subKey => $subValue) {
// if the value is an array and the key is numeric, it is a child element
if(is_array($subValue) && is_numeric($subKey)) {
$tmpChildrenKey = $subValue['ID'];
$tmpChildren[$tmpChildrenKey] = $subValue;
}
else { // otherwise it is an attribute
$tmpElementAttributes[$subKey] = $subValue;
}
}
$tmpElements[$key] = $tmpElementAttributes; // add the gathered attributes that define our firstLevel Element
}
So now we have two arrays. One ($tmpElements) has all the first Level Elements (Details, Systems) and the other one ($tmpChildren) has all the child Elements (First Name, Last Name, Cpu, City). For both arrays we took their id's as array key.
Now we iterate over the ordering array, filling in our child elements into the respective first level elements in our $tmpElements Array accoring to $order.
foreach($order as $key => $values) {
foreach($values as $orderId) {
$tmpElements[$key][] = $tmpChildren[$orderId];
}
}
Here, $key from the first array is the array key for our first level element, both in order as in your source/input and as in our $tmpElements. So we can use it to identify elements in our array.
The $orderId from the second foreach is the second level children element ID.
So we use it to reach our respective Children Element.
Hence: $tmpElements[$key][] = $tmpChildren[$orderId];

Categories