bestsource

지도의 NSRray 등가물

bestsource 2023. 10. 31. 22:26
반응형

지도의 NSRray 등가물

주어진NSArrayNSDictionary객체(유사한 객체 및 키 포함) 지정된 키 배열에 맵을 수행할 수 있습니까?예를 들어, 루비에서는 다음과 같은 작업을 수행할 수 있습니다.

array.map(&:name)

몇 줄 밖에 저장되지 않지만 NSRray에서는 카테고리를 사용합니다.블록이 영(0)으로 반환되지 않도록 해야 하지만, 그 외에는 다음과 같은 경우의 시간을 절약할 수 있습니다.-[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의 기능이 무엇인지는 모르겠지만 NSray에서 구현한 -valueForKey:를 찾고 계신 것 같습니다.전송합니다.-valueForKey:배열의 모든 요소로 이동하고 결과 배열을 반환합니다.수신 배열의 요소가 NSDictionary일 경우,-valueForKey:와 거의 같습니다.-objectForKey:. 키가 시작되지 않는 한 작동합니다.@

다른 모든 답변을 요약하면 다음과 같습니다.

루비(질문에서와 같이):

array.map{|o| o.name}

Obj-C(포함):

[array valueForKey:@"name"];

Obj-C(포함)valueForKeyPath, KVC 수집 연산자 참조):

[array valueForKeyPath:@"[collect].name"];

Obj-C(포함):

NSMutableArray *newArray = [NSMutableArray array];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
     [newArray addObject:[obj name]];
}];

스위프트(지도 포함, 폐쇄 참조)

array.map { $0.name }

그리고 보다 기능적인 방법으로 어레이를 처리할 수 있는 라이브러리가 몇 개 있습니다.다른 라이브러리를 설치하려면 코코아팟을 설치하는 것이 좋습니다.

업데이트: 스위프트를 사용하는 경우 지도를 참조하십시오.


BlocksKit은 옵션입니다.

NSArray *new = [stringArray bk_map:^id(NSString *obj) { 
    return [obj stringByAppendingString:@".png"]; 
}];

밑줄은 또 다른 옵션입니다.있습니다.mapfunction, 여기 웹사이트의 예가 있습니다.

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;

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"];

저는 Ruby 전문가가 아니기 때문에 100% 정확하게 대답할 자신이 없습니다. 하지만 'map'이 어레이의 모든 것에 어떤 작용을 하며 결과와 함께 새로운 어레이를 생성한다는 해석에 근거하여, 여러분이 원하는 것은 다음과 같습니다.

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


게시된 몇 개의 답변에 대한 약간의 개선.

  1. 0 확인—0을 사용하여 매핑할 때 개체를 제거할 수 있습니다.
  2. 메서드 이름은 메서드가 호출된 배열을 수정하지 않는다는 것을 더 잘 나타냅니다.
  3. 이것은 더 스타일적인 것이지만 IMO는 블록의 인수 이름을 개선했습니다.
  4. 카운트에 대한 점 구문

Objective-C의 경우, 다음 답변 목록에 ObjectiveSugar 라이브러리를 추가합니다. https://github.com/supermarin/ObjectiveSugar

게다가, 그것의 꼬리표는 "인간을 위한 목적적인 C 추가"입니다.OP에 잘 어울리는 루비 스타일 ;-)

가장 일반적인 사용 사례는 서버 호출에 의해 반환되는 사전을 간단한 개체의 배열에 매핑하는 것입니다. 예를 들어 NSDictionary 게시물에서 NSString ID의 NSray를 가져오는 것입니다.

NSArray *postIds = [results map:^NSString*(NSDictionary* post) {
                       return [post objectForKey:@"post_id"];
                   }];

Objective-C의 경우 다음 답변 목록에 Higher-Order-Functions를 추가합니다. https://github.com/fanpyi/Higher-Order-Functions;

JSON 배열 학생 J가 있습니다.SONList는 다음과 같습니다.

[
    {"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"];
}];

이를 위한 특별한 키 경로 연산자가 있습니다.@unionOfObjects. 대체된 것 같습니다.[collect]이전 버전에서.

상상해보세요.Transaction와 같은 부류의payee속성:

NSArray *payees = [self.transactions valueForKeyPath:@"@unionOfObjects.payee"];

배열 연산자에 대한 Apple 문서를 키 값 코딩으로 작성합니다.

스위프트가 새로운 지도 기능을 선보입니다.

다음은 설명서의 예입니다.

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"]

맵 함수는 임의 유형의 값을 반환하고 배열의 기존 값을 이 새로운 유형의 인스턴스에 매핑하는 닫힘을 사용합니다.

언급URL : https://stackoverflow.com/questions/6127638/nsarray-equivalent-of-map

반응형