2

I mean like python's chain.

Goal

chain([['a', 'b'], ['c', 'd', 'e'], ['f', 'g', 'h', 'i']]);
["a","b","c","d","e","f","g","h","i"]

Actually used but unpleasant solution

function chain($array_of_arrays)
{
    return call_user_func_array('array_merge', $array_of_arrays);
}

I'm actually not a big fan of call_user_func_array nor foreach, so I'm stuck here.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Julien Palard
  • 8,736
  • 2
  • 37
  • 44
  • 1
    how about using array_push? see here http://armantutorial.wordpress.com/2014/07/02/php-turning-multidimensional-arrays-to-single-dimension-arrays/ – rm_beginners Jul 15 '14 at 09:52
  • @rm_beginners Wouldn't array_push require a foreach considering the given input anyway ? – Clément Malet Jul 15 '14 at 09:54
  • array_push would consider TWO foreach )o: – Julien Palard Jul 15 '14 at 09:55
  • 3
    So to reiterate, you dislike a language construct intended to allow you to perform iterations, you dislike the solution you've presented that works.. Am I missing something or do we code purely so we can brag how beautiful our code is based on hipster standards or what? If it happens that PHP is really rubbing you the wrong way, I'd consider swapping to Python completely and simply ignoring PHP as a language. A programmer should be able to turn "ugly" solutions into beautiful ones (beautiful being arbitrary here). – N.B. Jul 15 '14 at 09:58
  • @N.B. : i think you are thinking way too much!! OP only wants an *equivalent* solution / method ...calm down!! :) – NoobEditor Jul 15 '14 at 10:02
  • I'm a C and Python dev, and today I have to write "some" PHP, I'm only trying to do my best so my code stay readable (Putting my call_user_func_array in an explicitly named function is a good start point, instead of writing it inline, it may be enough to keep me in peace.) – Julien Palard Jul 15 '14 at 10:03
  • @luvieere Not a duplicate, I'm not trying to group values under common keys. – Julien Palard Jul 15 '14 at 10:05
  • `$result = array_merge($first_array, $second_array, $third_array.... $nth_array);`. Alternatively you can create a variadic function `chain` that simply returns result of `array_merge`. – N.B. Jul 15 '14 at 10:06
  • @N.B.: I does not have my arrays in separated variables but in an array (actually the result of an array_map). And I don't know how many I have. – Julien Palard Jul 15 '14 at 10:09
  • @ulien Parad I thought you are using multi-dimentional array. – rm_beginners Jul 15 '14 at 10:09
  • If you're using php >= 5.5.0, you could basically use the exact same function as in python. demo: http://3v4l.org/mUDjV – Yoshi Jul 15 '14 at 10:47

3 Answers3

1

What about this:

function chain($array_of_arrays)
{
    return array_reduce($array_of_arrays,'array_merge',array());
}
clami219
  • 2,958
  • 1
  • 31
  • 45
  • 4
    Isn't this just a worse version than what the question already shows? – Jon Jul 15 '14 at 10:12
  • @Jon Well, it's a matter of opinion whether it's worse or not... OP asked for an alternative solution and there it is... If you think you have a better one, you can post it... :) – clami219 Jul 15 '14 at 10:14
  • @clami : i don't downvote answers, so *assume* i did -1 on this, its not about *alternative solution* but about *better alternative solution*!! :) – NoobEditor Jul 15 '14 at 10:15
  • I used "worse" in the sense that it's very close to the original and yet involves an additional function (`array_reduce`) that's not really required. Does more work to get the same result with no added value. – Jon Jul 15 '14 at 10:15
  • 1
    @NoobEditor Thanks, it's nice of you :) But still, I don't understand what's the problem with this answer... of course, it uses a method that is very similar to the one proposed by OP, but it uses a different logic... and the real point is that OP doesn't like to call call_user_func_array (I don't know why) or foreach loops, so I proposed a function that doesn't use either... that's it! If you can do better, again, post your answer and I'll upvote you! :) – clami219 Jul 15 '14 at 10:18
  • @clami219 : i don't know a better answer, so didn't posted...but i know this is *not* a better answer so commented!! ;) – NoobEditor Jul 15 '14 at 10:25
  • @NoobEditor Fair enough! It's your right to do so, isn't it! ;) – clami219 Jul 15 '14 at 10:26
0

Here's a 3-liner without call_user_func_array and foreach:

function chain($array)
{
    $return = [];

    array_walk_recursive($array, function($x) use (&$return) { $return[] = $x; });

    return $return;
}

That's actually how Laravel does it.

Quasdunk
  • 14,944
  • 3
  • 36
  • 45
0
$input = [['a', 'b'], ['c', 'd', 'e'], ['f', 'g', 'h', 'i']];

function test_call($input)
{
    return call_user_func_array('array_merge', $input);
}

function test_foreach($input)
{
    $result = [];

    foreach ($input as $array) {
        foreach ($array as $value) {
            $result[$value] = true;
        }
    }

    return array_keys($result);
}

function test_reduce($input)
{
    return array_reduce($input, 'array_merge', []);
}

$start = microtime(true);
for ($i = 0; $i < 1e5; ++$i) {
    test_call($input);
}
var_dump(microtime(true) - $start);

$start = microtime(true);
for ($i = 0; $i < 1e5; ++$i) {
    test_foreach($input);
}
var_dump(microtime(true) - $start);

$start = microtime(true);
for ($i = 0; $i < 1e5; ++$i) {
    test_reduce($input);
}
var_dump(microtime(true) - $start);

RESULTS

call_user_func_array - double(0.56941080093384)
foreach - double(0.70889902114868)
array_reduce - double(0.76243710517883)

Miraage
  • 3,334
  • 3
  • 26
  • 43
  • The problem is that I don't have my arrays in separate variables but in an array, and I don't know how many I have. – Julien Palard Jul 15 '14 at 10:27
  • Results of thins kind of test may be dependent of the number of arrays AND the number of values in each of them. Also I'm not searching for a fast solution, those times are neglictibles, I was searching for a readable/elegant one. – Julien Palard Jul 15 '14 at 12:06