Implode an multidimensional array by keys and values with PHP - php

I want to join the array keys to a filepath with the value at the end as file itself (the array below is a "filetree")
Array (depth, size and keynames are dynamic):
[0] => bla.tif
[1] => quux.tif
[foo] => Array (
[bar] => Array (
[lorem] => Array (
[1] => ipsum.tif
[2] => doler.tif
)
)
)
[bar] => Array (
[qux] => Array (
[baz] => Array (
[1] => ipsum.tif
[2] => ufo.tif
)
)
)
This result would be fine:
[0] => bla.tif
[1] => quux.tif
[2] => foo/bar/lorem/ipsum.tif
[3] => foo/bar/lorem/doler.tif
[4] => bar/qux/baz/ipsum.tif
[5] => bar/qux/baz/ufo.tif
Maybe there is also a pure PHP solution for that. I tried it with array_map but the results weren't fine enough.

I would use a recursive function to collapse this array. Here's an example of one:
function collapse($path, $collapse, &$result)
{
foreach($collapse AS $key => $value)
{
if(is_array($value))
{
collapse($path . $key . "/", $value, $result);
continue;
}
$result[] = $path . $value;
}
}
And here's how to use:
$result = array();
$toCollapse = /* The multidimentional array */;
collapse("", $toCollapse, $result);
and $result would contain the "imploded" array

Related

PHP Loop through array with no index names

In PHP I have this structure of Array (some are empty, some not, some are multiple items):
Array
(
[0] => Array
(
)
[1] => Array
(
[0] => 16534
)
[2] => Array
(
)
[3] => Array
(
[0] => 16532
[1] => 16533
)
[4] => Array
(
)
[5] => Array
(
[0] => 14869
)
}
I want to loop through this array, so as the result I get only the numbers (all of them).
I tried it this way:
foreach ($myarray as $item) {
echo '<pre>' . print_r($item) . '</pre>';
// $result[] = $this->myMethod($item);
}
So in foreach I want to use all the items from array in my method.
However when I echo the $item in the loop, I have something like this:
Array ( )
Array ( [0] => 16534 )
Array ( )
Array ( [0] => 16532 [1] => 16533 )
Array ( )
Array ( [0] => 14869 )
So still arrays (also the empty ones), and not numbers.
Can you please help with this?
UPDATE: I just noticed, some of the arrays looks like this:
[6] => Array
(
[0] => Array
(
[id] => 269
[hours] => 21.0
)
)
[7] => Array
(
[0] => Array
(
[0] => Array
(
[id] => 2
[hours] => 12.0
)
[1] => Array
(
[id] => 7
[hours] => 24.0
)
)
[1] => Array
(
[0] => Array
(
[id] => 2
[hours] => 5.0
)
[1] => Array
(
[id] => 7
[hours] => 0.583
)
)
)
but here the solution works not.
This one seems working but it is now brutal foreach in foreach solution:
foreach ($myarray as $item2) {
foreach ($item2 as $key2 => $val2) {
if (isset($val2)) {
foreach ($val2 as $key4 => $val4) {
echo $val4['id'].',';
}
}
}
}
Just merge the array which will also remove the empties:
foreach(array_merge(...$myarray) as $item) {
// echo '<pre>' . print_r($item) . '</pre>';
$result[] = $this->myMethod($item);
}
This will also work and may be faster:
$result = array_map([$this, 'myMethod'], array_merge(...$myarray));
If you have an old PHP version you'll have to use array() instead of [] and:
call_user_func_array('array_merge', $myarray)
You are only looping through the main array.That's the reason why you are getting an array when you are printing the result set.(because those values are stored in sub arrays and you are not looping them.)
And to remove the sub arrays with empty values I'll use isset() so that you will get only the values.
Change your code into this.
foreach ($myarray as $item) {
foreach($item as $key=>$val){
if(isset($val){
$values[] = $val;
// $result[] = $this->myMethod($values);
}
}
}

How to concatenate arrays element recursively [duplicate]

This question already has answers here:
Joining similar data from two indexed arrays
(2 answers)
Closed 5 months ago.
I'm working on a project and I'm stacked since 2 days, this is my problem: I have two arrays and want to retrieve the second item in each object in Array_2 and concatenate it to the content of each object in first Array_1 in PHP.
Array_1
[[1453274700000,24011],[1453275000000,24222],[1453275300000,24284],[1453275600000,24331],...]
Array_2
[[1453274700000,51951],[1453275000000,52093],[1453275300000,52251],[1453275600000,52288],...]
Wanted_array
[[1453274700000,24011,51951],[1453275000000,24222,52093],[1453275300000,24284,52251],[1453275600000,24331,52288]...]
A functional solution:
$result = array_map(function (array $a1, array $a2) {
return array_merge($a1, [$a2[1]]);
}, $array_1, $array_2);
This assumes that all items are in order and only need to be merged by their order, not by their first value.
If you want $item[0] to define what "group" each value belongs to, you can iterate through the first array and save $item[0] as the key and $item[1] as the value. Do the same for the second array. Now iterate through the saved array for array1, and check if the saved array for array2 contains the same keys. Do the same for array2 (in case it has key that array1 doesn't have), and save it all to a new array:
<?php
$arr1 = array(
array('1453274700000',24011),
array('1453275000000',24222),
array('1453276000000',24222), // inexistent in $arr2
);
$arr2 = array(
array('1453275000000',52093),
array('1453274700000',51951),
array('1453273000000',24222), // inexistent in $arr1
);
$arr1dictionary = [];
$arr2dictionary = [];
$result = [];
foreach ($arr1 as $collection) {
$arr1dictionary[$collection[0]] = $collection[1];
}
foreach ($arr2 as $collection) {
$arr2dictionary[$collection[0]] = $collection[1];
}
foreach ($arr1dictionary as $key => $value) {
if (isset($arr2dictionary[$key])) {
$result[$key] = [$key, $value, $arr2dictionary[$key]];
} else {
$result[$key] = [$key, $value, null];
}
}
foreach ($arr2dictionary as $key => $value) {
if (isset($result[$key])) {
continue;
}
$result[$key] = [$key, null, $value];
}
$result = array_values($result);
print_r($result);
Output:
Array
(
[0] => Array
(
[0] => 1453274700000
[1] => 24011
[2] => 51951
)
[1] => Array
(
[0] => 1453275000000
[1] => 24222
[2] => 52093
)
[2] => Array
(
[0] => 1453276000000
[1] => 24222
[2] => (null, the value only exists in $arr1)
)
[3] => Array
(
[0] => 1453273000000
[1] => (null, the value only exists in $arr2)
[2] => 24222
)
)
DEMO
Use array_walk and add second item from $array2 if it exists.
$array1 = array(
array(1453274700000,24011),
array(1453275000000,24222),
array(1453275300000,24284),
array(1453275600000,24331)
);
$array2 = array(
array(1453274700000,51951),
array(1453275000000,52093),
array(1453275300000,52251),
array(1453275600000,52288),
);
array_walk($array1, function(&$item, $key) use ($array2){
if(isset($array2[$key][1])){
$item[] = $array2[$key][1];
}
});
print_r($array1);
Output
Array
(
[0] => Array
(
[0] => 1453274700000
[1] => 24011
[2] => 51951
)
[1] => Array
(
[0] => 1453275000000
[1] => 24222
[2] => 52093
)
[2] => Array
(
[0] => 1453275300000
[1] => 24284
[2] => 52251
)
[3] => Array
(
[0] => 1453275600000
[1] => 24331
[2] => 52288
)
)
EDIT
As #h2ooooooo pointed out that there could be possibility that array items are in random order. If array items can be in random order and they are matched with first index value, use this (works with PHP >= 5.5.0):
$array1 = array(
array(1453274700000,24011),
array(1453275000000,24222),
array(1453275300000,24284),
array(1453275600000,24331),
array(1453276000000,24222) // no match in $array2
);
$array2 = array(
array(1453275000000,52093),
array(1453274700000,51951),
array(1453275300000,52251),
array(1453275600000,52288),
);
array_walk($array1, function(&$item, $key) use ($array2){
// Find match in $array2
$array2_key = array_search($item[0], array_column($array2, 0));
// If match found
if($array2_key !== false && isset($array2[$array2_key][1])){
$item[] = $array2[$array2_key][1];
}
// No match
else{
$item[] = null;
}
});
print_r($array1);
OUTPUT
Array
(
[0] => Array
(
[0] => 1453274700000
[1] => 24011
[2] => 51951
)
[1] => Array
(
[0] => 1453275000000
[1] => 24222
[2] => 52093
)
[2] => Array
(
[0] => 1453275300000
[1] => 24284
[2] => 52251
)
[3] => Array
(
[0] => 1453275600000
[1] => 24331
[2] => 52288
)
[4] => Array
(
[0] => 1453276000000
[1] => 24222
[2] =>
)
)

Recursive PHP Tree (permutations)

I'm looking to write a function which creates all permutation of a list of arrays (The list is dynamical). Now I found 2 articles, http://dannyherran.com/2011/06/finding-unique-array-combinations-with-php-permutations/ and Finding cartesian product with PHP associative arrays. But I don't want to store them as multiple arrays, I want to add each array to each possibility so I can use them later.
In fact I want to multiply each array with the other.
For example:
$array = array(
array(
1,
2
),
array(
'A',
'B',
'C'),
array(
'I',
'II')
);
In this form:
Array
(
[0] => Array
(
[0] => 1
[1] => Array
(
[0] => Array
(
[0] => A
[1] => Array
(
[0] => I
[1] => II
)
)
[1] => Array
(
[0] => B
[1] => Array
(
[0] => I
[1] => II
)
)
[2] => Array
(
[0] => C
[1] => Array
(
[0] => I
[1] => II
)
)
)
)
[1] => Array
(
[0] => 2
[1] => Array
(
[0] => Array
(
[0] => A
[1] => Array
(
[0] => I
[1] => II
)
)
[1] => Array
(
[0] => B
[1] => Array
(
[0] => I
[1] => II
)
)
[2] => Array
(
[0] => C
[1] => Array
(
[0] => I
[1] => II
)
)
)
)
)
I think this big example made my problem clear. For this type of array I created a function:
foreach ($array[1] as $value) {
$return1[] = array($value, $array[2]);
}
foreach ($array[0] as $value) {
$return[] = array($value, $return1);
}
print_r($return);
Now I want to create this function inside a recursive function (so it becomes dynamical) but I got stuck. I wanted to pass the amount of arrays to the function and then iterate.
function createTree($array, $loops=3){
$b = $array[$loops-2];
foreach ($b as $v) {
$return[] = array($v, createTree($return, $loops-1));
}
print_r($return);
}
Maybe there is a total other solution to multiply the arrays? But the function which isn't recursive is easy for me, but making it recursive...
Thanks for your help
function createTree($array){
switch(count($array)) {
case 0:
die('Illegal argument.');
case 1:
return $array[0];
default:
$lastArray = array_pop($array);
$subArray = createTree($array);
foreach ($lastArray as $item) {
$return[] = array($item, $subArray);
}
return $return;
}
}
var_dump(createTree(array_reverse($array)));

How to merge multidimensional arrays where only subarrays are affected? [duplicate]

This question already has answers here:
Merge row data from multiple arrays
(6 answers)
Closed 5 months ago.
here: Transforming array values in elements of a subarray using PHP I asked quite the same, but the arrays were flatter. I tried to adapt the code, but unfortunately without success.
How could I merge following arrays so the second array won't be added after the end of the first array, but each subarray of the first array will receive the correspondent values of subarrays of the second. In other words, I want to merge the subarrays. Here my example:
Array 01:
Array01 (
[0] => Array
(
[0] => 40292633
[1] => 412
)
[1] => Array
(
[0] => 41785603
[1] => 382
)
[2] => Array
(
[0] => 48792980
[1] => 373
)
[3] => Array
(
[0] => 44741143
[1] => 329
))
Array 02:
Array02(
[0] => Array
(
[0] => 3460581
[1] => 1407424B1
[2] => 951753
)
[1] => Array
(
[0] => 3484251
[1] => 1028325B1
[2] => 159357
)
[2] => Array
(
[0] => 3519102
[1] => 0586365A1
[2] => 456654
)
[3] => Array
(
[0] => 3529714
[1] => 1059876A1
[2] => 852258
))
Final array:
finalArray(
[0] => Array
(
[0] => 40292633
[1] => 412
[2] => 3460581
[3] => 1407424B1
[4] => 951753
)
[1] => Array
(
[0] => 41785603
[1] => 382
[2] => 3484251
[3] => 1028325B1
[4] => 159357
)
[2] => Array
(
[0] => 48792980
[1] => 373
[2] => 3519102
[3] => 0586365A1
[4] => 456654
)
[3] => Array
(
[0] => 44741143
[1] => 329
[2] => 3529714
[3] => 1059876A1
[4] => 852258
))
Many thanks in advance!
try this code
function merge_arrays($a1, $a2) {
return array($a1, $a2);
}
$result = array_map("merge_arrays", $a1, $a2);
foreach($result as $nr)
{
$nres[] = array_merge ($nr[0], $nr[1]);
}
Try this:
$result = array();
$keys = array_unique( array_merge(array_keys($arr1), array_keys($arr2)) );
foreach($keys as $key) {
if( !array_key_exists($key, $arr1) ) {
$result[$key] = $arr2;
} else if( !array_key_exists($key, $arr2) ) {
$result[$key] = $arr1;
} else {
$result[$key] = array_merge($arr1[$key], $arr2[$key]);
}
}
It does not assume that both arrays have the same keys.
If you'd like to use array_map, this is an equivalent solution:
$keys = array_unique( array_merge(array_keys($arr1), array_keys($arr2)) );
$result = array_map(function($key) use ($arr1,$arr2) {
if( !array_key_exists($key, $arr1) ) {
return $arr2;
} else if( !array_key_exists($key, $arr2) ) {
return $arr1;
}
return array_merge($arr1[$key], $arr2[$key]);
},
$keys);
If you're sure both arrays have the same keys, you can try this:
$result = array();
foreach($arr1 as $key => $arr1val) {
$result[$key] = array_merge($arr1val, $arr2[$key]);
}

PHP resort keys from multidimensional array

i have a multidimensional array whose index/keys (not the values) are like this:
this is how the submitted array looks
[param] => Array
(
[3] => groupedlista
[0] => groupedlistb
[2] => groupedlistc
)
[f_name] => Array
(
[3] => grouplistaa
[0] => grouplistbb
[2] => grouplistcc
)
[f_label] => Array
(
[3] => grouplistL3
[0] => grouplistL0
[2] => grouplistL2
)
this is how the order looks
0,2,3
i want that Result
[param] => Array
(
[0] => groupedlistb
[1] => groupedlistc
[2] => groupedlista
)
[f_name] => Array
(
[0] => grouplistbb
[1] => grouplistcc
[2] => grouplistaa
)
[f_label] => Array
(
[0] => grouplistL0
[1] => grouplistL2
[2] => grouplistL3
)
that's it
PS: i use a jquery sort / add / delete feature in the form and i prefer to do the final sorting php-based. the index array [$i] is required to be declared at the form.
$order = '0,2,3';
$out = array(); // This will hold the sorted values
$order = explode(',',$order); // Turn the order into an array
foreach ($multiDimArray as $key => $subArray) { // Loop outer array
foreach ($order as $pos) { // Loop order array
if (isset($subArray[$pos])) { // Make sure the key exists
$out[$key][] = $subArray[$pos]; // Put the correct value in the correct place
}
}
}
print_r($out);

Categories