Combine arrays to form multidimensional array in php - php

I know there's a ton of answers but I can't seem to get it right. I have the following arrays and what I've tried:
$a = array ( 0 => '1421' , 1 => '2241' );
$b = array ( 0 => 'teststring1' , 1 => 'teststring2' );
$c = array ( 0 => 'teststring3' , 1 => 'teststring4' );
$d = array ( 0 => 'teststring5' , 1 => 'teststring6' );
$e = array_combine($a, array($b,$c,$d) );
But with this I get the error array_combine() [function.array-combine]: Both parameters should have an equal number of elements.
I know it's because the $a's array values aren't keys. That's why I'm coming here to see if I could get some help with an answer that can help me make it look something like this:
array(2) {
[1421]=>array( [0] => teststring1
[1] => teststring3
[2] => teststring5
)
[2241]=>array( [0] => teststring2
[1] => teststring4
[2] => teststring6
)
}

If you have control over creating the arrays, you should create them like:
$a = array ('1421' ,'2241');
$b = array ('teststring1', 'teststring3', 'teststring5');
$c = array ('teststring2', 'teststring4', 'teststring6');
$e = array_combine($a, array($b,$c) );
If not, you have to loop over them:
$result = array();
$values = array($b, $c, $d);
foreach($a as $index => $key) {
$t = array();
foreach($values as $value) {
$t[] = $value[$index];
}
$result[$key] = $t;
}
DEMO

Here is a one-liner in a functional coding style. Calling array_map() with a null function parameter followed by the "values" arrays will generate the desired subarray structures. array_combine() does the key=>value associations.
Code (Demo)
var_export(array_combine($a, array_map(null, $b, $c, $d)));
Output:
array (
1421 =>
array (
0 => 'teststring1',
1 => 'teststring3',
2 => 'teststring5',
),
2241 =>
array (
0 => 'teststring2',
1 => 'teststring4',
2 => 'teststring6',
),
)
Super clean, right? I know. It's a useful little trick when you don't have control of the initial array generation step.

Here's a new version of array_merge_recursive which will handle integer keys. Let know how it goes.
$a = array ( 0 => '1421' , 1 => '2241' );
$b = array ( 0 => 'teststring1' , 1 => 'teststring2' );
$c = array ( 0 => 'teststring3' , 1 => 'teststring4' );
$d = array ( 0 => 'teststring5' , 1 => 'teststring6' );
$e = array_combine($a, array_merge_recursive2($b, $c, $d));
echo "<pre>";
print_r($e);
function array_merge_recursive2() {
$args = func_get_args();
$ret = array();
foreach ($args as $arr) {
if(is_array($arr)) {
foreach ($arr as $key => $val) {
$ret[$key][] = $val;
}
}
}
return $ret;
}

Related

Change list to list of associative arrays in PHP

I have list of unique elements and want to change it to list of associative arrays. What is the most elegant way to do this? I tried foreach but it looks bogus.
Expected Input:
array('2019-10-01', '2019-10-02', '2019-10-03')
Expected Output:
array(array('day' => '2019-10-01'), array('day' => '2019-10-02'), array('day' => '2019-10-03'))
You can use array_map:
$array = array('2019-10-01', '2019-10-02', '2019-10-03');
$output = array_map(function ($v) { return array('day' => $v); }, $array);
or a simple foreach:
$output = array();
foreach ($array as $v) {
$output[] = array('day' => $v);
}
In both cases the output is the same:
Array
(
[0] => Array
(
[day] => 2019-10-01
)
[1] => Array
(
[day] => 2019-10-02
)
[2] => Array
(
[day] => 2019-10-03
)
)
Demo on 3v4l.org
See this short code example. it iterates over the given array and associates a key with an increment:
$a = Array('2019-10-01', '2019-10-02', '2019-10-03');
$b = [];
for($x = 0; $x < count($a); $x++) {
$b['day' . $x] = $a[$x];
}
print_r($b);
// output: Array ( [day0] => 2019-10-01 [day1] => 2019-10-02 [day2] => 2019-10-03 )

PHP Array Restructuration

I have pairs of keys identified by their respective ID like this:
array(
'key_a_0' => $a,
'key_a_1' => $a,
'key_b_0' => $b,
'key_b_1' => $b
)
I need this structure:
array(
'0' => array(
'key_a' => $a,
'key_b' => $b
),
'1' => array(
'key_a' => $a,
'key_b' => $b
)
)
What would be the best way to achieve this?
Provided this is exactly how all the data is present as, and stays as, this would then be simple to amend into the format you require with a simple foreach loop.
$new = array();
foreach($data as $key => $variable){
list($name,$var,$index) = explode("_", $key);
$new[$index][$name . '_' . $var] = $variable;
}
This returns;
Array
(
[0] => Array
(
[key_a] => 5
[key_b] => 10
)
[1] => Array
(
[key_a] => 5
[key_b] => 10
)
)
Example
Ideally - you'd want to set your array structure at creation, as Dagon said.
The following should do the job. This assumes, however, that the initial array comes in a specific order and that order is what is expected within each nested array in the final array, and that the keys in the initial array are always in that format.
$a = 5;
$b = 10;
$aRawArray = array(
'key_a_0' => $a,
'key_a_1' => $a,
'key_b_0' => $b,
'key_b_1' => $b,
);
$aFormattedArray = array();
foreach ($aRawArray as $sKey => $mValue) {
$aKeyParts = explode('_', $sKey);
$sExtractedKey = $aKeyParts[2];
$sNewKey = $aKeyParts[0] . '_' . $aKeyParts[1];
if (!isset($aFormattedArray[$sExtractedKey])) {
$aFormattedArray[$sExtractedKey] = array();
}
$aFormattedArray[$sExtractedKey][$sNewKey] = $mValue;
}
var_dump($aFormattedArray);

Converting multidimensional array's values into a key value pair in a one-dimensional array while taking out a prefix out of one of the values?

I have an array in the following format:
Array (
[0] => Array
(
[option_id] => 10820
[option_name] => PREFIX_FIRST_OPT_KEY
[option_value] => FIRST_OPT_VALUE
[autoload] => yes
)
[1] => Array
(
[option_id] => 10821
[option_name] => PREFIX_SECOND_OPT_KEY
[option_value] => SECOND_OPT_VALUE
[autoload] => yes
)
[2] => Array
(
[option_id] => 10824
[option_name] => PREFIX_THIRD_OPT_KEY
[option_value] => SECOND_OPT_VALUE
[autoload] => yes
)
)
What is the appropriate function to use to get a one dimensional associative array with the following structure?
Array (
[FIRST_OPT_KEY] => FIRST_OPT_VALUE
[SECOND_OPT_KEY] => SECOND_OPT_VALUE
[THIRD_OPT_KEY] => THIRD_OPT_VALUE
)
I only want to keep the indicated values as key value pairs in the new array and ignore the rest - PREFIX_ is fixed length.
What I am doing right now:
foreach ( $the_original_array as $key => $value ) {
$new_key = substr($the_original_array[$key]['option_name'], 7);
$option_value = $the_original_array[$key]['option_value'];
$new_array[$new_key] = $option_value;
}
but I feel there ought to be a cleaner/more efficient way of accomplishing this
If you have PHP >= 5.5:
To extract values:
$result = array_column($array, 'option_value', 'option_name');
Then to remove prefix:
$result = array_combine(
array_map(
function($k){
return str_replace('PREFIX_', '', $k);
},
array_keys($result)
), $result
);
A way of simulating array_column() if you aren't running PHP 5.5+
$newArray = array_combine(
array_map(
function($value) {
return substr($value['option_name'], 7);
},
$the_original_array
),
array_map(
function($value) {
return $value['option_value'];
},
$the_original_array
)
);
The accepted answer is valid, but it causes the data to be iterated over multiple times. Assuming PHP < 5.5.0, using array_reduce will loop over the data only once, and return the same result:
$iterator = function($result, $record) {
$key = substr($record['option_name'], 7);
$result[$key] = $record['option_value'];
return $result;
};
$newArray = array_reduce($original, $iterator, array());
I would use array_column but for PHP < 5.5.0 what you have is about the best you can do, but you can use the $value that is generated by the foreach:
foreach ( $the_original_array as $value ) {
$new_key = substr($value['option_name'], 7);
$option_value = $value['option_value'];
$new_array[$new_key] = $option_value;
}
I think than foreach is good like:
$new = array();
foreach ($original_array as $item) {
$index = str_replace('PREFIX_', '', $item['option_name']);
$new[$index] = $item['option_value'];
}

PHP array to tree array

I have a problem I cannot fix. I have 2 arrays and a string. The first array contains the keys the second one should use. The first one is like this:
Array
(
[0] => foo
[1] => bar
[2] => hello
)
Now I need a PHP code that converts it to the second array:
Array
(
[foo] => Array
(
[bar] => Array
(
[hello] => MyString
)
)
)
The number of items is variable.
Can someone please tell me how to do this?
You should use references to solve this problem:
$a = array (0 => 'foo', 1 => 'bar', 2 => 'hello' );
$b = array();
$ptr = &$b;
foreach ($a as $val) {
$ptr[$val] = Array();
$ptr = &$ptr[$val];
}
$ptr = 'MyString';
var_dump($b);
All you need is :
$path = array(
0 => 'foo',
1 => 'bar',
2 => 'hello'
);
$data = array();
$t = &$data;
foreach ( $path as $key ) {
$t = &$t[$key];
}
$t = "MyString";
unset($t);
print_r($data);
See Live Demo

Create multidimensional array from rows

The result of a query in my database returns something like this (a record for each row):
1.
1.1.
1.1.01.
1.1.01.001
1.2.
1.2.01.
1.2.02.
I'm trying to create something that returns me a multidimensional array in a tree format, like this:
array(
'1.' => array(
'1.1' => array(
'1.1.01.' => array(
(int) 0 => '1.1.01.001'
)
),
'1.2' => array(
(int) 0 => '1.2.01.',
(int) 1 => '1.2.02.'
)
)
)
All I could think to do was reverse the order of elements using explode().
I appreciate any suggestions.
Your format is very tricky because of :
1.2.
1.2.01. |
1.2.02. V Making this array instead of value
You can try
$string = "1.
1.1.
1.1.01.
1.1.01.001
1.2.
1.2.01.
1.2.02.";
$array = explode("\n", $string);
$data = array();
$temp = &$data;
$it = new CachingIterator(new ArrayIterator($array), CachingIterator::FULL_CACHE);
$continue = false;
foreach ( $it as $v ) {
$v = trim($v);
if ($it->hasNext()) {
$next = trim($it->getInnerIterator()->current());
if (stripos($next, $v) === 0) {
$temp = &$temp[$v];
} else {
$temp[] = $v;
if (strlen($next) != strlen($v)) {
$temp = &$data;
}
}
} else {
$temp[] = $v;
}
}
print_r($data);
Output
Array
(
[1.] => Array
(
[1.1.] => Array
(
[1.1.01.] => Array
(
[0] => 1.1.01.001
)
)
)
[1.2.] => Array
(
[0] => 1.2.01.
[1] => 1.2.02.
)
)
Here is a move COMPLEX demo

Categories