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);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Alex
  • 23
  • 1
  • 5

3 Answers3

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);
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • 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 Aug 14 '16 at 20:00
  • @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 ^_^ – Mulan Aug 14 '16 at 20:04
  • @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 – Mulan Aug 14 '16 at 20:07
  • Thanks for the creative solution. Didn't realize `array_map` could be used with multiple arrays until I read your answer. +1. – BeetleJuice Aug 14 '16 at 21:39
  • `array_combine()` can be more elegantly replaced by `compact()` – mickmackusa Sep 17 '22 at 04:39
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
        )
)
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
  • 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. – Mulan Aug 15 '16 at 03:34
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.

BeetleJuice
  • 39,516
  • 19
  • 105
  • 165
  • foreach is more efficent –  Aug 14 '16 at 06:48
  • @Dagon You mean generally or in this case? Could you elaborate on why? Didn't know that – BeetleJuice Aug 14 '16 at 06:51
  • you run a count on every loop rather than jsut once –  Aug 14 '16 at 07:17
  • foreach($array1 as $ar1) this is what you are talking Dagon? – Alex Aug 14 '16 at 07:24
  • @Alex what? and why not? – BeetleJuice Aug 14 '16 at 07:56
  • @Dagon "efficiency" isn't the only metric by which we measure the quality of code. What do you mean by it, anyway? Is it *efficient* to compile? Is it *efficient* to execute? Is it *efficient* for programmers to read and understand? Is it *efficient* to debug? It's a loaded adjective, and even if one of those scenarios is true, it doesn't guarantee that the others off. Programming is full of trade-offs and varying situations will cause you to make differing choices. It would be dumb to always write code in a way that is X, Y, or Z, when the demands of the program are A-Z. – Mulan Aug 14 '16 at 19:08
  • @BeetleJuice your answer is fine and communicates its intent very clearly. Since this is a significant factor in code quality, I'd say you have provided a good answer. – Mulan Aug 14 '16 at 20:09