PHP list arrays - php

Is it possible to list arrays from an array with function?
I have configuration array of a plugin in which I wast to call function which will list arrays from array.
'fields' => array(
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something')
)
I made function:
function config(){
$a = array('id'=>'someidA','id'=>'somethingA');
$b = array('id'=>'someidB','id'=>'somethingB');
return array($a,$b);
}
When call config() function in array I get:
'fields' => array(
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array(
array('id'=>'someidA','id'=>'somethingA'),
array('id'=>'someidB','id'=>'somethingB')
)
)
But I need:
'fields' => array(
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someidA','id'=>'somethingA'),
array('id'=>'someidB','id'=>'somethingB')
)
I know this works:
'fields' => array(
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
array('id'=>'someid','id'=>'something'),
list($a,$b)=config(),
$a,$b,
)
But it does not help me too much, as sometime there are lot of $a,$,$c,$d etc, so it will be the best if somehow function could list those arrays.
Is there some ways to get rid of that container array and list arrays directly to another array?

array_merge will work for you. It merges 2 or more arrays into a single array.
<?php
$arr = array(
'fields' => array(
array('id1'=>'someid','id2'=>'something'),
array('id1'=>'someid','id2'=>'something'),
array('id1'=>'someid','id2'=>'something')
)
);
function config(){
$a = array('id1'=>'someidA','id2'=>'somethingA');
$b = array('id1'=>'someidB','id2'=>'somethingB');
return array($a,$b);
}
$config_arr = config();
$arr['fields'] = array_merge($arr['fields'], $config_arr);
print_r($arr);
?>
Working Example.
OUTPUT
Array
(
[fields] => Array
(
[0] => Array
(
[id1] => someid
[id2] => something
)
[1] => Array
(
[id1] => someid
[id2] => something
)
[2] => Array
(
[id1] => someid
[id2] => something
)
[3] => Array
(
[id1] => someidA
[id2] => somethingA
)
[4] => Array
(
[id1] => someidB
[id2] => somethingB
)
)
)

As an alternative to Samir's solution...
By using the "splat operator" (...) to unpack the returned array from config() and then array_push() to append both subarrays, you can achieve the desired result.
Code: (Demo)
$config = [
'fields' => [
['id1' => 'someid', 'id2' => 'something'],
['id1' => 'someid', 'id2' => 'something'],
['id1' => 'someid', 'id2' => 'something']
]
];
function config() {
$a = ['id1' => 'someidA','id2' => 'somethingA'];
$b = ['id1' => 'someidB','id2' => 'somethingB'];
return [$a, $b];
}
array_push($config['fields'], ...config());
var_export($config);

Related

How to remove the keys from a multi-dimensional associative array?

I have an associative array which has the following format:
array (
'Shopping and fashion' =>
array (
'childData' =>
array (
'Beauty' =>
array (
'childData' =>
array (
'Cosmetics' =>
array (
'id' => '6002839660079',
'name' => 'Cosmetics',
'parentName' => 'Beauty',
),
'Tattoos' =>
array (
'id' => '6003025268985',
'name' => 'Tattoos',
'parentName' => 'Beauty',
),),))))
I want to remove the keys from the array.
For this I am using :
array_values($my_data)
However, this only works for the topmost level of array, which in this case is "Shopping and fashion". It converts that to index 0.
How can I do the same for every array inside the index too?
EXPECTED OUTPUT:
array (
0 =>
array (
'childData' =>
array (
0 =>
array (
'childData' =>
array (
0 =>
array (
'id' => '6002839660079',
'name' => 'Cosmetics',
'parentName' => 'Beauty',
),
1 =>
array (
'id' => '6003025268985',
'name' => 'Tattoos',
'parentName' => 'Beauty',
),
),
'name' => 'Beauty',
'id' => '6002867432822',
'parentName' => 'Shopping and fashion',
),)))
The array I have has many different arrays on the parent level and many more array inside them so using for each is posing a problem as the number of "childData",i.e child arrays inside parent arrays are varying.
Could recursion be possible?
I don't know built-in function, but maybe this function would help you?
function array_values_recursive( $array ) {
$newArray = [];
foreach ( $array as $key => $value ) {
if ( is_array( $value ) ) {
$newArray[] = array_values_recursive( $value );
} else {
$newArray[$key] = $value;
}
}
return $newArray;
}

How can I avoid that array_merge_recursive() tranform properties into arrays?

I'm trying to array_merge_recursive two arrays.
$arrayA = array(
'properties' => array(
'path' => array(
'default' => '',
),
'multiple' => array(
'default' => true,
),
)
);
$arrayB = array(
'properties' => array(
'path' => array(
'default' => 'foo',
),
'multiple' => array(
'default' => false,
),
)
);
$array = array_merge_recursive($arrayA,$arrayB);
print_r($array);
Which gives
Array (
[properties] => Array (
[path] => Array (
[default] => Array (
[0] =>
[1] => foo
)
)
[multiple] => Array (
[default] => Array (
[0] => 1
[1] =>
)
)
)
)
As you can see, the default and multiple properties are merged into arrays since it exists in both arrays.
But I don't want them to be transformed into arrays, I want that the last value to override the previous one.
And of course they DO exists in both array, I cannot declare it only in the second one.
How could I achieve this ?
Thanks !

PHP Replace Array Values

I have 2 multidimensional arrays that I am working with:
$arr1 =
Array
([type] => characters
[version] => 5.6.7.8
[data] => Array
([Char1] => Array
([id] => 1
[name] =>Char1
[title] =>Example
[tags] => Array
([0] => DPS
[1] => Support))
[Char2] => Array
([id] => 2
[name] =>Char2
[title] =>Example
[tags] => Array
([0] => Tank
[1] => N/A)
)
)
etc...
$arr2=
Array
([games] => Array
([gameId] => 123
[gameType => Match
[char_id] => 1
[stats] => Array
([damage] => 55555
[kills] => 5)
)
([gameId] => 157
[gameType => Match
[char_id] => 2
[stats] => Array
([damage] => 12642
[kills] => 9)
)
etc...
Basically, I need almost all the data in $arr2... but only the Char name from $arr1. How could I merge or add the $arr1['name'] key=>value into $arr2 where $arr1['id'] is equal to $arr2['char_id'] as the "id" field of each array is the same number.
I've attempted using array_merge and array_replace, but I haven't come up with any working solutions. This is also all data that I am receiving from a 3rd party, so I have no control on initial array setup.
Thanks for any help or suggestions!
Actually, this is quite straighforward. (I don't think there a built-in function that does this.)
Loop $arr2 and under it loop also $arr1. While under loop, just add a condition that if both ID's match, add that particular name to $arr2. (And use some referencing & on $arr2)
Consider this example:
// your data
$arr1 = array(
'type' => 'characters',
'version' => '5.6.7.8',
'data' => array(
'Char1' => array(
'id' => 1,
'name' => 'Char1',
'title' => 'Example',
'tags' => array('DPS', 'Support'),
),
'Char2' => array(
'id' => 2,
'name' => 'Char2',
'title' => 'Example',
'tags' => array('Tank', 'N/A'),
),
),
);
$arr2 = array(
'games' => array(
array(
'gameId' => 123,
'gameType' => 'Match',
'char_id' => 1,
'stats' => array('damage' => 55555, 'kills' => 5),
),
array(
'gameId' => 157,
'gameType' => 'Match',
'char_id' => 2,
'stats' => array('damage' => 12642, 'kills' => 9),
),
),
);
foreach($arr2['games'] as &$value) {
$arr2_char_id = $value['char_id'];
// loop and check against the $arr1
foreach($arr1['data'] as $element) {
if($arr2_char_id == $element['id']) {
$value['name'] = $element['name'];
}
}
}
echo '<pre>';
print_r($arr2);
$arr2 should look now like this:
Array
(
[games] => Array
(
[0] => Array
(
[gameId] => 123
[gameType] => Match
[char_id] => 1
[stats] => Array
(
[damage] => 55555
[kills] => 5
)
[name] => Char1 // <-- name
)
[1] => Array
(
[gameId] => 157
[gameType] => Match
[char_id] => 2
[stats] => Array
(
[damage] => 12642
[kills] => 9
)
[name] => Char2 // <-- name
)
)
)
Iterate over $arr2 and add the data to it from the matching $arr1 array value:
$i = 0;
foreach($arr2['games'] as $arr2Game){
$id = $arr2Game['char_id'];
$arr2['games'][$i]['name'] = $arr1['data'][$id]['name'];
$i++;
}
Have not tested this code.
If I'm understanding you correctly, you want to add a name index to each of the arrays within the $arr2['games'] array.
foreach($arr2['games'] as $key => $innerArray)
{
$arr2['games'][$key]['name'] = $arr1['data']['Char'.$innerArray['char_id']]['name'];
}

Array_merge_recursive gives me repeat data, how to remove it

I have the following 2 arrays that I'm trying to merge recursively so that I don't lose data, but I also don't want any data repeated.
$a = array(
'group1' => array(
'names' => array(
'g1name1',
'g1name2'
)
),
'group2' => array(
'names' => array(
'g2name1'
)
)
);
$b = array(
'group1' => array(
'names' => array(
'g1name1',
'g1name3'
),
'extras' => array(
'g1extra1'
)
),
'group3' => array(
'names' => array(
'g3name1'
)
)
);
I'm using array_merge_recursive($a, $b); which works fine for group2 and group3 because they exist in either $a or $b, but group1 is giving me a problem because it has some duplicate data in both $a and $b. This is what I'm getting after I merge recursively. Notice that in names, g1name is listed twice, once from $a and once from $b.
'group1' =>
array
'names' =>
array
0 => string 'g1name1'
1 => string 'g1name2'
2 => string 'g1name1'
3 => string 'g1name3'
'extras' =>
array
0 => string 'g1extra1'
1 => string 'g1extra2'
'group2' => ....
'group3' => ....
I tried array_unique like this array_unique(array_merge_recursive($a, $b)) but it's giving me strange results (doesn't fix the repeat problem and deletes group2 and group3 entirely).
Use array_replace_recursive instead of array_merge_recursive.
The the following should work for you:
array_walk($arr, function(&$data, $key) {
foreach ($data as &$arr) {
$arr = array_values(array_unique($arr));
}
});
Result:
Array
(
[group1] => Array
(
[names] => Array
(
[0] => g1name1
[1] => g1name2
[2] => g1name3
)
[extras] => Array
(
[0] => g1extra1
)
)
[group2] => Array
(
[names] => Array
(
[0] => g2name1
)
)
[group3] => Array
(
[names] => Array
(
[0] => g3name1
)
)
)
Sadly, array_replace_recursive (PHP 5.3.0)­Docs does not work (Demo).
Luckily Tim Cooper pointed that out and made some suggestion. I was not very creative with my new suggestion, so it's highly influenced by his solution:
$result = array_merge_recursive($a, $b);
array_walk($result, function(&$v) {
$v = array_map('array_unique', $v);
});
New Demo

Which PHP Array function should I use?

I have two arrays:
Array
(
[0] => Array
(
[id] => 1
[type] => field
[remote_name] => Title
[my_name] => title
[default_value] => http%3A%2F%2Ftest.com
)
[1] => Array
(
[id] => 2
[type] => field
[remote_name] => BookType
[my_name] => book-type
[default_value] =>
)
[2] => Array
(
[id] => 3
[type] => value
[remote_name] => dvd-disc
[my_name] => dvd
[default_value] =>
)
)
Array
(
[title] => Test
[book-type] => dvd
)
I need to take each key in the second array, match it with the my_name value in the first array and replace it with the corresponding remote_name value of the first array while preserving the value of the second array.
There's got to be some carrayzy function to help!
EDIT: There will also be a few cases that the value of the second array will need to be replaced by the value of the first array's remote_name where the value of the second array matches the value of the first array's my_name. How can I achieve this?
EG: book-type => dvd should turn into BookType => dvd-disc
Like so?:
$first = array(
array(
'id' => 1,
'type' => 'field',
'remote_name' => 'Title',
'my_name' => 'title',
'default_value' => 'http%3A%2F%2Ftest.com',
),
array(
'id' => 2,
'type' => 'field',
'remote_name' => 'BookType',
'my_name' => 'book-type',
'default_value' => '',
),
array(
'id' => 3,
'type' => 'value',
'remote_name' => 'dvd-disc',
'my_name' => 'dvd',
'default_value' => '',
),
);
$second = array(
'title' => 'Test',
'book-type' => 'dvd',
);
$map = array('fields' => array(), 'values' => array());
foreach ($first as $entry) {
switch ($entry['type']) {
case 'field':
$map['fields'][$entry['my_name']] = $entry['remote_name'];
break;
case 'value':
$map['values'][$entry['my_name']] = $entry['remote_name'];
break;
}
}
$new = array();
foreach ($second as $key => $val) {
$new[isset($map['fields'][$key]) ? $map['fields'][$key] : $key] = isset($map['values'][$val]) ? $map['values'][$val] : $val;
}
print_r($new);
Output:
Array
(
[Title] => Test
[BookType] => dvd-disc
)
Explanation:
The first loop collects the my_name/remote_name pairs for fields and values and makes them more accessible.
Like so:
Array
(
[fields] => Array
(
[title] => Title
[book-type] => BookType
)
[values] => Array
(
[dvd] => dvd-disc
)
)
The second loop will traverse $second and use the key/value pairs therein to populate $new. But while doing so will check for key/value duplicates in $map.
Keys or values not found in the map will be used as is.
foreach($arr1 as &$el) {
$el['remote_name'] = $arr2[$el['my_name']];
}
unset($el);
I am not aware of such a carrayzy function, but I know how you could do it:
//$array1 is first array, $array2 is second array
foreach($array1 as $key => $value){
if (isset($value['remote_name'], $value['my_name']) && $value['remote_name'] && $value['my_name']){
$my_name = $value['my_name'];
if (isset($array2[$my_name])) {
$remote_name = $value['remote_name'];
$array2[$remote_name] = $array2[$my_name];
//cleanup
unset($array2[$my_name]);
}
}
}

Categories