[ios] 정렬 된 키가있는 NSDictionary

기본적으로 연관 배열 (키와 값으로 문자열)로 사용하는 NSDictionary (plist에 저장 됨)가 있습니다. 응용 프로그램의 일부로 키 배열을 사용하고 싶지만 특정 순서 (정렬 할 알고리즘을 작성할 수있는 순서가 아님)를 원합니다. 나는 항상 별도의 키 배열을 저장할 수 있지만, 항상 사전의 키와 배열의 값을 업데이트하고 항상 일치하는지 확인해야했기 때문에 다소 까다로워 보입니다. 현재는 [myDictionary allKeys] 만 사용하고 있지만 분명히 임의의 비 보장 순서로 반환합니다. Objective-C에 누락 된 데이터 구조가 있습니까? 누구든지 이것을 더 우아하게 수행하는 방법에 대한 제안이 있습니까?



답변

관련된 NSMutableArray 키를 갖는 솔루션은 그리 나쁘지 않습니다. NSDictionary의 서브 클래 싱을 피하고 접근 자 작성에주의를 기울이면 동기화를 유지하는 것이 너무 어렵지 않아야합니다.


답변

실제 답변으로 게임에 늦었지만 CHOrderedDictionary 조사에 관심이있을 수 있습니다 . 키 순서를 유지하기 위해 다른 구조를 캡슐화하는 NSMutableDictionary의 하위 클래스입니다. ( CHDataStructures.framework 의 일부입니다 .) 딕셔너리와 배열을 별도로 관리하는 것보다 더 편리하다고 생각합니다.

공개 : 이것은 내가 작성한 오픈 소스 코드입니다. 이 문제에 직면 한 다른 사람들에게 유용 할 수 있기를 바랍니다.


답변

이것을 얻을 수있는 내장 된 방법은 없습니다. 그러나 간단한 논리가 작동합니다. 사전을 준비하는 동안 각 키 앞에 숫자 텍스트를 몇 개만 추가하면됩니다. 처럼

NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:
                       @"01.Created",@"cre",
                       @"02.Being Assigned",@"bea",
                       @"03.Rejected",@"rej",
                       @"04.Assigned",@"ass",
                       @"05.Scheduled",@"sch",
                       @"06.En Route",@"inr",
                       @"07.On Job Site",@"ojs",
                       @"08.In Progress",@"inp",
                       @"09.On Hold",@"onh",
                       @"10.Completed",@"com",
                       @"11.Closed",@"clo",
                       @"12.Cancelled", @"can",
                       nil];

이제 모든 키를 배치 한 순서대로 가져 오는 동안 sortingArrayUsingSelector를 사용할 수 있다면.

NSArray *arr =  [[dict allKeys] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];

UIView에서 키를 표시하려는 위치에서 앞의 3 개 문자를 잘라냅니다.


답변

NSDictionary를 하위 클래스로 만들려면 최소한 다음 메서드를 구현해야합니다.

  • NSDictionary
    • -count
    • -objectForKey:
    • -keyEnumerator
  • NSMutableDictionary
    • -removeObjectForKey:
    • -setObject:forKey:
  • NSCopying / NSMutableCopying
    • -copyWithZone:
    • -mutableCopyWithZone:
  • NSCoding
    • -encodeWithCoder:
    • -initWithCoder:
  • NSFastEnumeration (Leopard 용)
    • -countByEnumeratingWithState:objects:count:

원하는 작업을 수행하는 가장 쉬운 방법은 조작하는 자체 NSMutableDictionary와 정렬 된 키 집합을 저장하는 NSMutableArray를 포함하는 NSMutableDictionary의 하위 클래스를 만드는 것입니다.

당신이 당신의 객체를 인코딩하기 위해가는 일은 없습니다 경우 구현 건너 생각할 수 -encodeWithCoder:-initWithCoder:

위의 10 개 메서드의 모든 메서드 구현은 호스팅 된 사전 또는 순서가 지정된 키 배열을 통해 직접 이동합니다.


답변

내 작은 추가 사항 : 숫자 키로 정렬하기 (작은 코드에 단축 표기법 사용)

// the resorted result array
NSMutableArray *result = [NSMutableArray new];
// the source dictionary - keys may be Ux timestamps (as integer, wrapped in NSNumber)
NSDictionary *dict =
@{
  @0: @"a",
  @3: @"d",
  @1: @"b",
  @2: @"c"
};

{// do the sorting to result
    NSArray *arr = [[dict allKeys] sortedArrayUsingSelector:@selector(compare:)];

    for (NSNumber *n in arr)
        [result addObject:dict[n]];
}


답변

빠르고 더러운 :

사전 (이하 “myDict”라고 함)을 주문해야하는 경우 다음과 같이하십시오.

     NSArray *ordering = [NSArray arrayWithObjects: @"Thing",@"OtherThing",@"Last Thing",nil];

그런 다음 사전을 주문해야 할 때 색인을 만듭니다.

    NSEnumerator *sectEnum = [ordering objectEnumerator];
    NSMutableArray *index = [[NSMutableArray alloc] init];
        id sKey;
        while((sKey = [sectEnum nextObject])) {
            if ([myDict objectForKey:sKey] != nil ) {
                [index addObject:sKey];
            }
        }

이제 * index 객체는 올바른 순서로 적절한 키를 포함합니다. 이 솔루션은 모든 키가 반드시 존재해야하는 것은 아니며, 우리가 다루는 일반적인 상황입니다.


답변

For, Swift 3 . 다음 접근 방식을 시도하십시오

        //Sample Dictionary
        let dict: [String: String] = ["01.One": "One",
                                      "02.Two": "Two",
                                      "03.Three": "Three",
                                      "04.Four": "Four",
                                      "05.Five": "Five",
                                      "06.Six": "Six",
                                      "07.Seven": "Seven",
                                      "08.Eight": "Eight",
                                      "09.Nine": "Nine",
                                      "10.Ten": "Ten"
                                     ]

        //Print the all keys of dictionary
        print(dict.keys)

        //Sort the dictionary keys array in ascending order
        let sortedKeys = dict.keys.sorted { $0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedAscending }

        //Print the ordered dictionary keys
        print(sortedKeys)

        //Get the first ordered key
        var firstSortedKeyOfDictionary = sortedKeys[0]

        // Get range of all characters past the first 3.
        let c = firstSortedKeyOfDictionary.characters
        let range = c.index(c.startIndex, offsetBy: 3)..<c.endIndex

        // Get the dictionary key by removing first 3 chars
        let firstKey = firstSortedKeyOfDictionary[range]

        //Print the first key
        print(firstKey)