Câu hỏi NSDictionary với các phím đặt hàng


Tôi tò mò nếu đây là một tình huống bất kỳ folks khác đã tìm thấy chính mình in Tôi có một NSDictionary (được lưu trữ trong một plist) mà tôi về cơ bản sử dụng như là một mảng kết hợp (chuỗi như các phím và giá trị). Tôi muốn sử dụng các mảng của các phím như một phần của ứng dụng của tôi, nhưng tôi muốn chúng được theo một thứ tự cụ thể (không thực sự là một thứ tự mà tôi có thể viết một thuật toán để sắp xếp chúng thành). Tôi luôn luôn có thể lưu trữ một mảng riêng biệt của các phím, nhưng điều đó có vẻ như loại kludgey bởi vì tôi luôn luôn phải cập nhật các phím của từ điển cũng như các giá trị của mảng, và chắc chắn rằng chúng luôn luôn tương ứng. Hiện tại tôi chỉ sử dụng [myDictionary allKeys], nhưng rõ ràng điều này trả về chúng theo thứ tự tùy ý, không bảo đảm. Có một cấu trúc dữ liệu trong Objective-C mà tôi đang thiếu? Có ai có bất cứ đề nghị về cách thanh lịch hơn làm điều này?


76
2017-12-17 21:27


gốc




Các câu trả lời:


Giải pháp có NSMutableArray liên quan đến các khóa không phải là quá tệ. Nó tránh subclassing NSDictionary, và nếu bạn cẩn thận với việc viết accessors, nó không nên quá khó để giữ đồng bộ.


23
2017-12-17 22:19



Một điều đáng tiếc là NS (Mutable) Dictionary tạo các bản sao của các khóa, vì vậy các đối tượng trong mảng khóa sẽ khác nhau. Điều này có thể có vấn đề nếu một khóa bị đột biến. - Quinn Taylor
Đó là một điểm tốt, nhưng giảm nhẹ nếu khả năng đột biến bị hạn chế thêm và loại bỏ đối tượng khỏi mảng thay vì thay đổi các mục bên trong chúng. - Abizern
Không chắc chắn cách bạn hạn chế ai đó sửa đổi khóa mà họ đã cung cấp con trỏ ở địa điểm đầu tiên. Mảng chỉ lưu trữ một con trỏ tới khóa đó và sẽ không biết nó có thay đổi hay không. Nếu khóa được thay đổi, thậm chí bạn không thể xóa mục nhập bổ sung khỏi mảng, đây có thể là sự cố đồng bộ hóa thực nếu bạn giữ các khóa không còn trong từ điển hoặc ngược lại ...: -) - Quinn Taylor
BTW, xin lỗi của tôi nếu tôi âm thanh quá quan trọng. Tôi đã tự giải quyết vấn đề này, nhưng vì nó là một khuôn khổ, tôi đang cố gắng thiết kế nó một cách mạnh mẽ và chính xác trong mọi tình huống có thể tưởng tượng được. Bạn đúng là một mảng riêng biệt không vì thế xấu, nhưng nó không đơn giản như một lớp học theo dõi nó cho bạn. Thêm vào đó, có rất nhiều lợi ích nếu một lớp như vậy mở rộng từ điển NS (Mutable), vì nó có thể được sử dụng ở bất kỳ đâu một từ điển Cocoa. - Quinn Taylor
Tôi không quan tâm đến cuộc thảo luận. Đề nghị của tôi chỉ là một cách giải quyết. Viết một khuôn khổ là một đề xuất hoàn toàn khác nhau và nó là cái gì đó cần suy nghĩ cẩn thận. Cá nhân, tôi thấy sự bất tiện gây phiền hà vì lý do này, và tôi cố gắng giảm thiểu việc sử dụng các lớp đó trong các chương trình của riêng tôi. - Abizern


Tôi đến trễ trò chơi với câu trả lời thực tế, nhưng bạn có thể quan tâm để điều tra CHOrderedDictionary. Đó là một lớp con của NSMutableDictionary đóng gói một cấu trúc khác để duy trì thứ tự khóa. (Đó là một phần của CHDataStructures.framework.) Tôi thấy nó thuận tiện hơn việc quản lý từ điển và mảng riêng biệt.

Tiết lộ: Đây là mã nguồn mở mà tôi đã viết. Chỉ hy vọng nó có thể hữu ích cho những người khác phải đối mặt với vấn đề này.


18
2017-10-18 19:04



+1 - Chưa thử nhưng xem qua các tài liệu và có vẻ như bạn đã thực hiện một số công việc tuyệt vời ở đây. Tôi nghĩ đó là một chút xấu hổ Apple đang thiếu rất nhiều những nguyên tắc cơ bản. - Lee
Nó không chỉ là một từ điển đặt hàng bị thiếu, nó là rất nhiều bộ sưu tập CS101 hữu ích đang mất tích. Tôi không tin Objective-C sẽ là một ngôn ngữ thành công rộng rãi mà không có Apple, trái ngược với C, C ++, Java, C #, đã chứng minh thành công nhiều lần ngoài tầm nhìn của người sáng tạo của họ. - Lee
Điều này. Là. Tuyệt vời. Xấu hổ tôi đã không phát hiện ra khuôn khổ này cho đến bây giờ. Đây sẽ là trụ cột trong hầu hết các dự án trong tương lai. Cảm ơn rất nhiều! - Dev Kanchen
Liên kết bị hỏng. - zakdances
github.com/quinntaylor/CHDataStructures - Avijit Nagare


Không có phương pháp sẵn có như vậy mà từ đó bạn có thể có được điều này. Nhưng một công việc logic đơn giản cho bạn. Bạn có thể chỉ cần thêm vài chữ số ở trước mỗi phím trong khi chuẩn bị từ điển. Như

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

Bây giờ nếu bạn có thể sử dụng sortingArrayUsingSelector trong khi nhận được tất cả các phím theo thứ tự như bạn đặt.

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

Tại nơi bạn muốn hiển thị các phím trong UIView, chỉ cần cắt bỏ 3 ký tự phía trước.


15
2018-02-22 09:14



Điều này cho thấy cách xóa ba ký tự đầu tiên: stackoverflow.com/questions/1073872/… - Leon


Nếu bạn đang đi đến lớp con NSDictionary bạn cần phải thực hiện các phương pháp này như là một tối thiểu:

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

Cách dễ nhất để làm những gì bạn muốn là tạo một lớp con của NSMutableDictionary chứa NSMutableDictionary của chính nó mà nó thao tác và một NSMutableArray để lưu trữ một bộ khóa có thứ tự.

Nếu bạn sẽ không bao giờ mã hóa các đối tượng của mình, bạn có thể hình dung được việc bỏ qua -encodeWithCoder: và -initWithCoder:

Tất cả các phương pháp triển khai phương pháp của bạn trong 10 phương pháp trên sẽ sau đó hoặc đi trực tiếp thông qua từ điển được lưu trữ hoặc mảng khóa được sắp xếp của bạn.


7
2017-12-18 04:40



Có một điều nữa không rõ ràng và vấp ngã tôi - nếu bạn triển khai NSCoding, cũng ghi đè lên - (Class) classForKeyedArchiver để trả về [class tự]. Các nhóm lớp thiết lập điều này để luôn trả về lớp cha trừu tượng, vì vậy trừ khi bạn thay đổi điều đó, các cá thể sẽ luôn được giải mã dưới dạng từ điển NS (Mutable). - Quinn Taylor


Bổ sung nhỏ của tôi: sắp xếp theo phím số (Sử dụng ký pháp viết tắt cho mã nhỏ hơn)

// 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]];
}

5
2018-03-20 13:58





Nhanh chóng 'n bẩn:

Khi bạn cần đặt hàng từ điển của bạn (ở đây gọi là “myDict”), hãy làm như sau:

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

Sau đó, khi bạn cần đặt hàng từ điển của mình, hãy tạo chỉ mục:

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

Bây giờ, đối tượng chỉ mục * sẽ chứa các khóa thích hợp theo đúng thứ tự. Lưu ý rằng giải pháp này không yêu cầu tất cả các khóa nhất thiết phải tồn tại, đó là tình huống thông thường mà chúng ta đang xử lý ...


3
2017-08-13 03:47



Điều gì về sortArrayUsingSelector cho thứ tự mảng? developer.apple.com/library/ios/documentation/cocoa/Conceptual/… - Alex Zavatone


Vì, Swift 3. Vui lòng thử phương pháp sau

        //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)

2
2017-10-19 12:25