Skip to content

Commit

Permalink
Use Dictionary instead of arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
dpolac committed Jun 11, 2016
1 parent ba2e1ed commit 703d444
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 86 deletions.
103 changes: 31 additions & 72 deletions LambdaExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

namespace DPolac\TwigLambda;

use DPolac\Dictionary;

class LambdaExtension extends \Twig_Extension
{
Expand Down Expand Up @@ -79,7 +80,7 @@ public static function map($array, $callback)
if (is_array($array)) {
$array = array_map($callback, $array, array_keys($array));
} elseif ($array instanceof \Traversable) {
$result = [];
$result = new Dictionary();
foreach ($array as $i => $item) {
$result[$i] = $callback($item, $i);
}
Expand All @@ -102,7 +103,7 @@ public static function filter($array, $callback)
if (is_array($array)) {
$array = array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
} elseif ($array instanceof \Traversable) {
$result = [];
$result = new Dictionary();
foreach ($array as $i => $item) {
if ($callback($item, $i)) {
$result[$i] = $item;
Expand Down Expand Up @@ -134,10 +135,15 @@ public static function uniqueBy($array, $callback)
}

if ($array instanceof \Traversable) {
$array = iterator_to_array($array);
if ($array instanceof \Iterator) {
// convert Iterator to IteratorAggregate for nested foreach
$array = Dictionary::fromArray($array);
}
$result = new Dictionary();
} else {
$result = [];
}

$result = [];

foreach ($array as $i => $item) {
foreach ($array as $j => $previous) {
if ($i === $j) {
Expand All @@ -152,15 +158,8 @@ public static function uniqueBy($array, $callback)
return $result;
}

public static function groupBy($array, $callback, $keyType = 'detect')
public static function groupBy($array, $callback)
{
$keyType = strtolower($keyType);

if (!in_array($keyType, ['scalar', 'object', 'detect'])) {
throw new \Twig_Error_Runtime(sprintf(
'Third argument of "group_by" must be one of "scalar", "object" and "detect", '.
'but is "%s".', $keyType));
}

if (!is_callable($callback)) {
throw new \Twig_Error_Runtime(sprintf(
Expand All @@ -172,65 +171,20 @@ public static function groupBy($array, $callback, $keyType = 'detect')
'First argument of "group_by" must be array or Traversable, but is "%s".', gettype($array)));
}

$results = [];
$hashes = [];
$results = new Dictionary();

foreach ($array as $i => $item) {
$key = $callback($item, $i);

if ('detect' === $keyType) {
if (is_object($key)) {
$keyType = 'object';
} else if (is_scalar($key)) {
$keyType = 'scalar';
} else {
throw new \Twig_Error_Runtime(sprintf(
'Only allowed values returned by "group_by" are '.
'callback are scalars and objects with implemented __toString() method, '.
'but it returned "%s".', gettype($key)));
}
if (!isset($results[$key])) {
$results[$key] = [$i => $item];
} else {
$results[$key][$i] = $item;
}

if ('scalar' === $keyType) {
if (is_object($key) && method_exists($key, '__toString')) {
$key = (string)$key;
} elseif (!is_scalar($key)) {
throw new \Twig_Error_Runtime(sprintf(
'Only allowed values returned by "group_by" callback with "scalar" ' .
'as key type are scalars and objects with implemented __toString() method, ' .
'but it returned "%s".', gettype($key)));
}

if (!isset($results[$key])) {
$results[$key] = [$i => $item];
} else {
$results[$key][$i] = $item;
}
} elseif ('object' === $keyType) {
if (!is_object($key)) {
throw new \Twig_Error_Runtime(sprintf(
'Only allowed values returned by "group_by" callback with "object" ' .
'as key type are objects, but it returned "%s".', gettype($key)));
}

$hash = \spl_object_hash($key);
$hashes[$hash] = $key;

if (!isset($results[$hash])) {
$results[$hash] = [$i => $item];
} else {
$results[$hash][$i] = $item;
}
}
}

if ('scalar' === $keyType) {
return $results;
} elseif ('object' === $keyType) {
return new GroupByObjectIterator($results, $hashes);
} else {
// $keyType is still 'detect' if $array is empty
return [];
}
return $results;
}

public static function sortBy($array, $callback, $direction = 'ASC')
Expand All @@ -246,13 +200,18 @@ public static function sortBy($array, $callback, $direction = 'ASC')
}

if ($array instanceof \Traversable) {
$array = iterator_to_array($array);
if ($array instanceof Dictionary) {
$array = $array->getCopy();
} else {
$array = Dictionary::fromArray($array);
}
return $array->sortBy($callback, $direction);
} else {
$direction = (strtoupper($direction) === 'DESC') ? SORT_DESC : SORT_ASC;
$order = self::map($array, $callback);
array_multisort($order, $direction, SORT_REGULAR, $array);
return $array;
}

$direction = (strtoupper($direction) === 'DESC') ? SORT_DESC : SORT_ASC;
$order = self::map($array, $callback);
array_multisort($order, $direction, SORT_REGULAR, $array);
return $array;
}

public static function countBy($array, $callback)
Expand All @@ -267,7 +226,7 @@ public static function countBy($array, $callback)
'First argument of "count_by" must be array or Traversable, but is "%s".', gettype($array)));
}

$result = [];
$result = new Dictionary();
foreach ($array as $i => $element) {
$key = $callback($element, $i);
if (is_bool($key)) {
Expand Down
14 changes: 1 addition & 13 deletions Tests/Fixtures/filters/count_by.test
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,4 @@ return [ 'data' => [
--EXPECT--
null: 3
true: 1
false: 2
--DATA--
return [ 'data' => [
[ 'foo' => 1 ],
[ 'foo' => 1 ],
[ 'foo' => -1 ],
[ 'foo' => 1.2 ],
[ 'foo' => -1.3 ],
[ 'foo' => 1.9 ],
] ];
--EXPECT--
1: 4
-1: 2
false: 2
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
],
"require": {
"php": "^5.4 || ^7.0",
"twig/twig": "^1.0"
"twig/twig": "^1.0",
"dpolac/dictionary": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "~5.0"
Expand Down

0 comments on commit 703d444

Please sign in to comment.