Created
October 20, 2017 22:24
-
-
Save ostrolucky/2947154fae206e876b6c5e1abed0a25e to your computer and use it in GitHub Desktop.
Array flatten algorithms benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$array = [1, 2, 3, 4, [], [5, 6], 7, 8, [9], [10, [11, 12], 13, [14, 15, 16, [17, [18, [19, 20, 21]]]]], 22, 23, 24, [25], 26, [27, [28], [29, [30, 31], [32], [33, [34, [35, 36], 37, 38, [39, 40]]]]]]; | |
function laravel_flatten($array, $depth = INF) | |
{ | |
return array_reduce($array, function ($result, $item) use ($depth) { | |
if (! is_array($item)) { | |
return array_merge($result, [$item]); | |
} elseif ($depth === 1) { | |
return array_merge($result, array_values($item)); | |
} else { | |
return array_merge($result, laravel_flatten($item, $depth - 1)); | |
} | |
}, []); | |
} | |
function knapsack_flatten($collection, $levelsToFlatten = -1) | |
{ | |
$generatorFactory = function () use ($collection, $levelsToFlatten) { | |
$flattenNextLevel = $levelsToFlatten < 0 || $levelsToFlatten > 0; | |
$childLevelsToFlatten = $levelsToFlatten > 0 ? $levelsToFlatten - 1 : $levelsToFlatten; | |
foreach ($collection as $key => $value) { | |
if ($flattenNextLevel && (is_array($value) || $value instanceof Traversable)) { | |
foreach (knapsack_flatten($value, $childLevelsToFlatten) as $childKey => $childValue) { | |
yield $childKey => $childValue; | |
} | |
} else { | |
yield $key => $value; | |
} | |
} | |
}; | |
$collection = $generatorFactory(); | |
$generatorFactory2 = function() use ($collection) { | |
foreach ($collection as $value) { | |
yield $value; | |
} | |
}; | |
return iterator_to_array($generatorFactory2()); | |
} | |
$tests = [ | |
'lstrojny/functional-php' => function ($array) { | |
$stack = [$array]; | |
$result = []; | |
while (!empty($stack)) { | |
$item = array_shift($stack); | |
if (is_array($item)) { | |
foreach ($item as $element) { | |
array_unshift($stack, $element); | |
} | |
} else { | |
array_unshift($result, $item); | |
} | |
} | |
return $result; | |
}, | |
'laravel collections' => 'laravel_flatten', | |
'dusank/knapsack' => 'knapsack_flatten', | |
'recursive_iterator' => function ($array) { | |
return iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)), false); | |
}, | |
'array_walk_recursive' => function ($array) { | |
$return = array(); | |
array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; }); | |
return $return; | |
}, | |
]; | |
foreach ($tests as $suite => $closure) { | |
$time = microtime(true); | |
for ($i=0;$i<100000;$i++) { | |
call_user_func($closure, $array); | |
} | |
echo $suite.' finished in '.(microtime(true) - $time) . 's'.PHP_EOL; | |
} | |
/* | |
lstrojny/functional-php finished in 3.0966401100159s | |
laravel collections finished in 2.0682859420776s | |
dusank/knapsack finished in 4.2100491523743s | |
recursive_iterator finished in 1.9282908439636s | |
array_walk_recursive finished in 0.74895691871643s | |
*/ |
This was made for very specific use case, not as general specific solution
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
recursive_iterator is wrong, because it will not work with objects.
Need use SELF_FIRST, or extends RecursiveArrayIterator with override hasChildren.