지도와 동등한 NSArray
감안할 때 NSArray의 NSDictionary그 지정된 키의 배열에 대한지도 작성을 수행 할 수있다 (유사한 목적 및 키를 포함하는) 객체는? 예를 들어 Ruby에서는 다음과 같이 할 수 있습니다.
array.map(&:name)
업데이트 : Swift를 사용하는 경우 map을 참조하십시오 .
BlocksKit 은 옵션입니다.
NSArray *new = [stringArray bk_map:^id(NSString *obj) {
return [obj stringByAppendingString:@".png"];
}];
밑줄 은 또 다른 옵션입니다. map기능 이 있습니다. 다음은 웹 사이트의 예입니다.
NSArray *tweets = Underscore.array(results)
// Let's make sure that we only operate on NSDictionaries, you never
// know with these APIs ;-)
.filter(Underscore.isDictionary)
// Remove all tweets that are in English
.reject(^BOOL (NSDictionary *tweet) {
return [tweet[@"iso_language_code"] isEqualToString:@"en"];
})
// Create a simple string representation for every tweet
.map(^NSString *(NSDictionary *tweet) {
NSString *name = tweet[@"from_user_name"];
NSString *text = tweet[@"text"];
return [NSString stringWithFormat:@"%@: %@", name, text];
})
.unwrap;
몇 줄만 저장하지만 NSArray에서 범주를 사용합니다. 블록이 nil을 반환하지 않도록해야하지만 그 외에는 -[NSArray valueForKey:]작동하지 않는 경우 시간을 절약 할 수 있습니다.
@interface NSArray (Map)
- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block;
@end
@implementation NSArray (Map)
- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block {
NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[result addObject:block(obj, idx)];
}];
return result;
}
@end
사용법은 다음과 같습니다 -[NSArray enumerateObjectsWithBlock:].
NSArray *people = @[
@{ @"name": @"Bob", @"city": @"Boston" },
@{ @"name": @"Rob", @"city": @"Cambridge" },
@{ @"name": @"Robert", @"city": @"Somerville" }
];
// per the original question
NSArray *names = [people mapObjectsUsingBlock:^(id obj, NSUInteger idx) {
return obj[@"name"];
}];
// (Bob, Rob, Robert)
// you can do just about anything in a block
NSArray *fancyNames = [people mapObjectsUsingBlock:^(id obj, NSUInteger idx) {
return [NSString stringWithFormat:@"%@ of %@", obj[@"name"], obj[@"city"]];
}];
// (Bob of Boston, Rob of Cambridge, Robert of Somerville)
Ruby가 무엇을하는지 모르겠지만 NSArray의 -valueForKey : 구현을 찾고 있다고 생각 합니다 . 이것은 배열의 모든 요소로 보내고 결과의 배열을 반환합니다. 수신 배열의 요소가 NSDictionaries 인 경우 는 . 키가로 시작하지 않는 한 작동합니다.-valueForKey:-valueForKey:-objectForKey:@
다른 모든 답변을 요약하려면 :
루비 (질문에서와 같이) :
array.map{|o| o.name}
Obj-C ( valueForKey 사용 ) :
[array valueForKey:@"name"];
Obj-C (valueForKeyPath 포함, KVC 컬렉션 연산자 참조 ) :
[array valueForKeyPath:@"[collect].name"];
Obj-C ( enumerateObjectsUsingBlock 사용 ) :
NSMutableArray *newArray = [NSMutableArray array];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[newArray addObject:[obj name]];
}];
array.map { $0.name }
그리고보다 기능적인 방식으로 배열을 처리 할 수있는 몇 가지 라이브러리가 있습니다. Cocoa Pods 는 다른 라이브러리를 설치하는 데 권장됩니다.
valueForKeyPath가 좋은 선택이라고 생각합니다.
아래에 앉아 매우 멋진 예가 있습니다. 도움이 되길 바랍니다.
http://kickingbear.com/blog/archives/9
몇 가지 예 :
NSArray *names = [allEmployees valueForKeyPath: @"[collect].{daysOff<10}.name"];
NSArray *albumCovers = [records valueForKeyPath:@"[collect].{artist like 'Bon Iver'}.<NSUnarchiveFromDataTransformerName>.albumCoverImageData"];
저는 루비 전문가가 아니기 때문에 정확히 대답하고 있다고 100 % 확신하지는 못합니다.하지만 '맵'이 배열의 모든 것에 무언가를하고 그 결과로 새로운 배열을 생성한다는 해석을 바탕으로 여러분이 아마도 원하는 것은 다음과 같습니다.
NSMutableArray *replacementArray = [NSMutableArray array];
[existingArray enumerateObjectsUsingBlock:
^(NSDictionary *dictionary, NSUInteger idx, BOOL *stop)
{
NewObjectType *newObject = [something created from 'dictionary' somehow];
[replacementArray addObject:newObject];
}
];
따라서 OS X 10.6 / iOS 4.0에서 '블록'(보다 일반적인 용어로 클로저)에 대한 새로운 지원을 사용하여 어레이의 모든 항목에 대해 블록의 작업을 수행하고 있습니다. 몇 가지 작업을 수행 한 다음 결과를 별도의 배열에 추가하도록 선택합니다.
10.5 또는 iOS 3.x를 지원하려는 경우 관련 코드를 객체에 넣고 makeObjectsPerformSelector를 사용하는 방법을 살펴 보거나 최악의 경우 for(NSDictionary *dictionary in existingArray).
@implementation NSArray (BlockRockinBeats)
- (NSArray*)mappedWithBlock:(id (^)(id obj, NSUInteger idx))block {
NSMutableArray* result = [NSMutableArray arrayWithCapacity:self.count];
[self enumerateObjectsUsingBlock:^(id currentObject, NSUInteger index, BOOL *stop) {
id mappedCurrentObject = block(currentObject, index);
if (mappedCurrentObject)
{
[result addObject:mappedCurrentObject];
}
}];
return result;
}
@end
게시 된 몇 가지 답변에 약간의 개선이 있습니다.
- nil을 확인합니다. 매핑 할 때 nil을 사용하여 개체를 제거 할 수 있습니다.
- 메서드 이름은 메서드가 호출 된 배열을 수정하지 않는다는 것을 더 잘 반영합니다.
- 이것은 스타일에 가깝지만 IMO가 블록의 인수 이름을 개선했습니다.
- 카운트에 대한 점 구문
For Objective-C, I would add the ObjectiveSugar library to this list of answers: https://github.com/supermarin/ObjectiveSugar
Plus, its tagline is "ObjectiveC additions for humans. Ruby style." which should suit OP well ;-)
My most common use-case is mapping an dictionary returned by a server call to an array of simpler objects e.g. getting an NSArray of NSString IDs from your NSDictionary posts:
NSArray *postIds = [results map:^NSString*(NSDictionary* post) {
return [post objectForKey:@"post_id"];
}];
For Objective-C, I would add the Higher-Order-Functions to this list of answers: https://github.com/fanpyi/Higher-Order-Functions;
There is a JSON array studentJSONList like this:
[
{"number":"100366","name":"Alice","age":14,"score":80,"gender":"female"},
{"number":"100368","name":"Scarlett","age":15,"score":90,"gender":"female"},
{"number":"100370","name":"Morgan","age":16,"score":69.5,"gender":"male"},
{"number":"100359","name":"Taylor","age":14,"score":86,"gender":"female"},
{"number":"100381","name":"John","age":17,"score":72,"gender":"male"}
]
//studentJSONList map to NSArray<Student *>
NSArray *students = [studentJSONList map:^id(id obj) {
return [[Student alloc]initWithDictionary:obj];
}];
// use reduce to get average score
NSNumber *sum = [students reduce:@0 combine:^id(id accumulator, id item) {
Student *std = (Student *)item;
return @([accumulator floatValue] + std.score);
}];
float averageScore = sum.floatValue/students.count;
// use filter to find all student of score greater than 70
NSArray *greaterthan = [students filter:^BOOL(id obj) {
Student *std = (Student *)obj;
return std.score > 70;
}];
//use contains check students whether contain the student named 'Alice'
BOOL contains = [students contains:^BOOL(id obj) {
Student *std = (Student *)obj;
return [std.name isEqual:@"Alice"];
}];
Swift introduces a new map function.
Here is an example from the documentation:
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
// strings is inferred to be of type String[]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]
The map function takes a closure which returns a value of any type and maps the existing values in the array to instances of this new type.
참고URL : https://stackoverflow.com/questions/6127638/nsarray-equivalent-of-map
'IT TIP' 카테고리의 다른 글
| 구성 [Spring-Boot]에서 '패키지'유형의 빈 정의를 고려하십시오. (0) | 2020.10.27 |
|---|---|
| Java의 URL과 일치하는 정규식 (0) | 2020.10.27 |
| MySQL 열거 형 대 집합 (0) | 2020.10.27 |
| 변수에서 일괄 추출 경로 및 파일 이름 (0) | 2020.10.27 |
| 뷰를 사용하여 PHP에서 현재 Laravel 버전의 버전을 어떻게 에코 할 수 있습니까? (0) | 2020.10.27 |