1

I have three arrays for instance

Array1 array (size=3) 0 => string 'a' (length=1) 1 => string 'b' (length=1) 2 => string 'c' (length=1) Array2 array (size 3) 0 => string '$' (length=1) 1 => string '%' (length=1) 2 => string '^' (length=1) Array3 array (size 3) 0 => int '1' (length=1) 1 => int '2' (length=1) 2 => int '3' (length=1) 

I want an array4 to be have this configuration that each array's each row should be one group. For instance

Array4 0th name=a type=$ price=1 1st name=b type=% price=2 2nd name=c type=^ price=3 

I tried this and gave me perfect result

$output = array_combine($array1, $array2); 

But when I tried this it wouldn't give expected result

$output = array_combine(array_combine($array, $array2),$array3); 
1
  • one foreach() loop would work Commented Aug 14, 2016 at 6:29

3 Answers 3

6

utilizing functional helpers

By using array_map and array_combine, you can skip having to handle things like counts, iterators, manual array assignment, and manual array combining.

This solution reduces complexity by using procedures which hide all that complexity behind useful, functional APIs.

$names = ['a', 'b', 'c']; $types = ['$', '%', '^']; $prices = [1, 2, 3]; $result = array_map(function ($name, $type, $price) { return array_combine( ['name', 'type', 'price'], [$name, $type, $price] ); }, $names, $types, $prices); echo json_encode($result, JSON_PRETTY_PRINT); 

Output (some line-breaks removed for brevity)

[ {"name": "a", "type": "$", "price": 1}, {"name": "b", "type": "%", "price": 2}, {"name": "c", "type": "^", "price": 3} ] 

hiding your own complexity

You can even abstract away your own complexity by defining your own procedure, array_zip_combine — which works like array_combine but accepts multiple input arrays which are first "zipped" before being combined

this solution requires PHP 7+

// PHP 7 offers rest parameter and splat operator to easily apply variadic function function array_zip_combine (array $keys, ...$arrs) { return array_map(function (...$values) use ($keys) { return array_combine($keys, $values); }, ...$arrs); } $result = array_zip_combine(['name', 'type', 'price'], $names, $types, $prices); 

same solution for PHP 5.4+

// PHP 5 doesn't offer splat operator so we have to use // call_user_func_array to apply a variadic function function array_zip_combine (array $keys /* args */) { $f = function () use ($keys) { return array_combine($keys, func_get_args()); }; return call_user_func_array( 'array_map', array_merge([$f], array_slice(func_get_args(), 1)) ); } $result = array_zip_combine(['name', 'type', 'price'], $names, $types, $prices); 
Sign up to request clarification or add additional context in comments.

5 Comments

I'm trying to understand your PHP 7+ solution. I think I'm missing something. The function declaration never mentions the values. Is that ok? I would have expected function array_zip_combine($keys, ...$values) to be the declaration
@BeetleJuice thanks for noticing. I was using array_slice(func_get_args(), 1) so the code still worked, but a rest parameter is a much better fit. I first wrote the PHP 5 one and then forgot the rest parameter when converting to PHP 7 ^_^
@BeetleJuice I ended up removing func_get_args() from the inner function too. PHP 7 feels a bit nicer getting rid of those archaic APIs
Thanks for the creative solution. Didn't realize array_map could be used with multiple arrays until I read your answer. +1.
array_combine() can be more elegantly replaced by compact()
3

Simple solution using array_map and array_combine functions:

$result = array_map(function($item) { return array_combine(['name', 'type', 'price'], $item); }, array_map(null, $array1, $array2, $array3)); print_r($result); 

The output:

Array ( [0] => Array ( [name] => a [type] => $ [price] => 1 ) [1] => Array ( [name] => b [type] => % [price] => 2 ) [2] => Array ( [name] => c [type] => ^ [price] => 3 ) ) 

1 Comment

It's a little peculiar that this answer arrives just moments after mine, seeing as tho it's virtually identical. Anyway, the nested array_map does double the amount of iteration as is necessary. I would recommend implementing like I did array_zip_combine if you're trying to make the answer more readable but still keeping iteration at a minimum.
2

If you know that all three arrays are the same length and have all required data, a simple fix would be to iterate over that length and build your results array:

$result = []; $count = count($array1); for($i=0; $i < $count; $i++){ $result[$i] = [ 'name'=>$array1[$i], 'type'=>$array2[$i], 'price'=>$array3[$i] ]; } 

$result holds what you need. What you're trying -- array_combined() -- is not made to build one array with values from the others so it won't work for this purpose. That function is to build an array whose keys come from one array and values from another.

7 Comments

foreach is more efficent
@Dagon You mean generally or in this case? Could you elaborate on why? Didn't know that
you run a count on every loop rather than jsut once
foreach($array1 as $ar1) this is what you are talking Dagon?
@Alex what? and why not?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.