Skip to content

Commit

Permalink
adding ability to find and filter by attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
dperrymorrow committed Mar 3, 2016
1 parent 38593e8 commit cff1505
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ Returns a copy of the array containing no duplicate values. Unlike Underscore.js
__::uniq(array(2, 2, 4, 4, 4, 1, 1, 1)); // array(2, 4, 1)
```

## union
### union

```php
__::union(*arrays)
Expand Down
21 changes: 20 additions & 1 deletion test/CollectionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

class UnderscoreCollectionsTest extends PHPUnit_Framework_TestCase {

public $assoc = [
["name" => "joe", "job" => "plumber"],
["name" => "fred", "job" => "plumber"],
["name" => "john", "job" => "barber"],
];

public function testEach() {
// from js
$test =& $this;
Expand Down Expand Up @@ -87,6 +93,13 @@ public function testFind() {
$this->assertEquals(2, __::find(array(1,2,3), function($num) { return $num * 2 === 4; }), 'found the first "2" and broke the loop');

// extra
$this->assertEquals(__::find($this->assoc, ['name' => 'fred'])['name'], 'fred');
$this->assertEquals(__::find($this->assoc, ['name' => 'fred', 'job' => 'plumber'])['name'], 'fred');

$obj = (object) $this->assoc;
$this->assertEquals(__::find($obj, ['name' => 'fred'])['name'], 'fred');
$this->assertEquals(__::find($obj, ['name' => 'fred', 'job' => 'plumber'])['name'], 'fred');

$iterator = function($n) { return $n % 2 === 0; };
$this->assertEquals(2, __::find(array(1, 2, 3, 4, 5, 6), $iterator));
$this->assertEquals(false, __::find(array(1, 3, 5), $iterator));
Expand All @@ -112,7 +125,13 @@ public function testFilter() {
$iterator = function($num) { return $num % 2 !== 0; };
$this->assertEquals(__::filter(array(1,3,5), $iterator), __::select(array(1,3,5), $iterator), 'alias works');

// docs
$this->assertEquals(__::filter($this->assoc, ['job' => "barber"])[0]['name'], 'john');
$this->assertEquals(__::filter($this->assoc, ['job' => "plumber", 'name' => 'fred'])[0]['name'], 'fred');

$obj = (object) $this->assoc;
$this->assertEquals(__::filter($obj, ['job' => "barber"])[0]['name'], 'john');
$this->assertEquals(__::filter($obj, ['job' => "plumber", 'name' => 'fred'])[0]['name'], 'fred');

$this->assertEquals(array(2,4), __::filter(array(1, 2, 3, 4), function($num) { return $num % 2 === 0; }));
}

Expand Down
26 changes: 23 additions & 3 deletions underscore.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,13 @@ public function filter($collection=null, $iterator=null) {
list($collection, $iterator) = self::_wrapArgs(func_get_args(), 2);

$collection = self::_collection($collection);
$iterator = __::isArray($iterator) ? $this->matchFunct($iterator) : $iterator;

$return = array();
$return = [];
foreach($collection as $val) {
if(call_user_func($iterator, $val)) $return[] = $val;
if (call_user_func($iterator, $val)) $return[] = $val;
}

return self::_wrap($return);
}

Expand All @@ -229,10 +231,11 @@ public function detect($collection=null, $iterator=null) { return self::find($co
public function find($collection=null, $iterator=null) {
list($collection, $iterator) = self::_wrapArgs(func_get_args(), 2);

$iterator = __::isArray($iterator) ? $this->matchFunct($iterator) : $iterator;
$collection = self::_collection($collection);

foreach($collection as $val) {
if(call_user_func($iterator, $val)) return $val;
if (call_user_func($iterator, $val)) return $val;
}
return self::_wrap(false);
}
Expand Down Expand Up @@ -1128,6 +1131,23 @@ private function _wrapArgs($caller_args, $num_args=null) {
return array_pad($filled_args, $num_args, null);
}

private function matchFunct($keyVals) {
return function ($item) use ($keyVals) {
foreach($keyVals as $key => $val) {
if ($this->getVal($item, $key) !== $val) return false;
}
return true;
};
}

private function getVal($item, $key) {
if (__::isObject($item)) {
return property_exists($item, $key) ? $item->{$key} : null;
} elseif (__::isArray($item)) {
return array_key_exists($key, $item) ? $item[$key] : null;
}
return null;
}

// Get a collection in a way that supports strings
private function _collection($collection) {
Expand Down

0 comments on commit cff1505

Please sign in to comment.