1. keroxp
Changes in title
-NSArray+Pluck
+NSArray+Where
Changes in body
Source | HTML | Preview
@@ -1,80 +1,81 @@
-Underscore.jsにarray.pluckというとても便利なメソッドがある。
+**※修正。pluckとwhereを間違えてましたorz**
+Underscore.jsにarray.whereというとても便利なメソッドがある。
```javascript
-var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
-_.pluck(stooges, 'name');
-// => ["moe", "larry", "curly"]
+_.where(listOfPlays, {author: "Shakespeare", year: 1611});
+//=> [{title: "Cymbeline", author: "Shakespeare", year: 1611},
+ {title: "The Tempest", author: "Shakespeare", year: 1611}]
```
あまりにも便利すぎるのでObjective-Cでも使いたくなったので実装した。
多分n番煎じだと思う。
cocoaにはvalueForKeyPath:という便利なアクセッサがあるので、入れ子になったNSDictionaryやオブジェクトなどのプロパティも比較できる。
-```objectivec:NSArray+Pluck.h
-@interface NSArray (Pluck)
+```objectivec:NSArray+Where.h
+@interface NSArray (Where)
-- (NSArray*)pluckUsingSelector:(SEL)selector value:(id)value;
-- (NSArray*)pluckForKeyPath:(NSString*)keyPath comparingSelector:(SEL)selector value:(id)value;
+- (NSArray*)whereUsingSelector:(SEL)selector value:(id)value;
+- (NSArray*)whereForKeyPath:(NSString*)keyPath comparingSelector:(SEL)selector value:(id)value;
@end
```
-```objectivec:NSArray+Pluck.m
+```objectivec:NSArray+Where.m
#import <objc/message.h>
-@implementation NSArray (Pluck)
+@implementation NSArray (Where)
-- (NSArray *)pluckUsingSelector:(SEL)selector value:(id)value
+- (NSArray *)whereUsingSelector:(SEL)selector value:(id)value
{
- return [self pluckForKeyPath:nil comparingSelector:selector value:value];
+ return [self whereForKeyPath:nil comparingSelector:selector value:value];
}
-- (NSArray *)pluckForKeyPath:(NSString *)keyPath comparingSelector:(SEL)selector value:(id)value
+- (NSArray *)whereForKeyPath:(NSString *)keyPath comparingSelector:(SEL)selector value:(id)value
{
NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count];
for (id obj in self) {
id target = keyPath ? [obj valueForKeyPath:keyPath] : obj;
if ([target respondsToSelector:selector]){
if(objc_msgSend(target, selector, value)) {
[array addObject:obj];
}
}
}
return [NSArray arrayWithArray:array];
}
@end
```
こんな感じで使えます。
-```objectivec:NSARray+PluckTests.m
+```objectivec:NSARray+WhereTests.m
- (void)testBasic
{
NSArray *a = @[@"a",@"b",@"c",@"ab",@"cd",@"a"];
- NSArray *p = [a pluckUsingSelector:@selector(isEqualToString:) value:@"a"];
+ NSArray *p = [a whereUsingSelector:@selector(isEqualToString:) value:@"a"];
XCTAssert(p.count == 2, );
for (NSString *s in p) {
XCTAssert([s isEqualToString:@"a"], );
}
}
- (void)testKeyPath
{
NSArray *a = @[
@{@"hoge": @"hogeval"},
@{@"fuga" : @"fugaval"},
@{@"var" : @"varval"},
@{@"hoga" : @"hogaval"},
@{@"hoge": @"hogeval2"}
];
- NSArray *p1 = [a pluckUsingSelector:@selector(objectForKey:) value:@"hoge"];
+ NSArray *p1 = [a whereUsingSelector:@selector(objectForKey:) value:@"hoge"];
XCTAssert(p1.count == 2, @"key hogeを持っているのは一つだけ");
- NSArray *p2 = [a pluckUsingSelector:@selector(isKindOfClass:) value:[NSDictionary class]];
+ NSArray *p2 = [a whereUsingSelector:@selector(isKindOfClass:) value:[NSDictionary class]];
XCTAssert(p2.count == a.count, @"全部辞書形");
- NSArray *p3 = [a pluckForKeyPath:@"hoge" comparingSelector:@selector(isEqualToString:) value:@"hogeval"];
+ NSArray *p3 = [a whereForKeyPath:@"hoge" comparingSelector:@selector(isEqualToString:) value:@"hogeval"];
XCTAssert(p3.count == 1, @"key hogeの値がhogevalなのは1つだけ");
}
```