2009-07-01 42 views
62

Cách hiệu quả nhất để sắp xếp các đối tượng trong một số NSSet/NSMutableSet dựa trên thuộc tính của các đối tượng trong bộ này là gì? Ngay bây giờ cách tôi đang làm nó là bằng cách lặp qua từng đối tượng, thêm chúng vào một NSMutableArray và sắp xếp mảng đó với NSSortDescriptor.Cách hiệu quả nhất để sắp xếp một NSSet là gì?

Trả lời

111

hãy thử sử dụng

[[mySet allObjects] sortedArrayUsingDescriptors:descriptors]; 

Sửa: Đối với iOS ≥ 4.0 và Mac OS X ≥ 10,6 bạn có thể trực tiếp sử dụng

[mySet sortedArrayUsingDescriptors:descriptors]; 
+0

Ngắn và ngọt ngào! – Boon

+5

Điều này không khác nhiều so với gợi ý của người hỏi, và có lẽ gần như tương đương về tốc độ vì -allObjects trả về một NSArray tự động, và -sortedArrayUsingDescriptors: trả về một NSArray riêng biệt (cả hai đều không thay đổi). Chi phí phân bổ hai mảng không thấp hơn nhiều so với liệt kê tất cả các phần tử trong một tập hợp (kích thước vừa phải) và yêu cầu nhiều gấp đôi không gian. –

+1

Bạn nên lưu ý rằng sortArrayUsingDescriptors: là phương thức chỉ 10.6. Nếu bạn đang nhắm mục tiêu 10.5 hoặc trước khi bạn có thể thử cách tiếp cận của @ QuinnTaylor – Austin

2

NSSet là tập hợp các đối tượng không có thứ tự. Nhìn vào tài liệu tham khảo của apple Mảng được sắp xếp theo thứ tự.

Nhìn vào NSArray có một cuộc thảo luận với các ví dụ phân loại tại http://developer.apple.com/documentation/Cocoa/Conceptual/Collections/Articles/sortingFilteringArrays ...

Ví dụ từ liên kết:

NSInteger alphabeticSort(id string1, id string2, void *reverse) 
{ 
    if (*(BOOL *)reverse == YES) { 
     return [string2 localizedCaseInsensitiveCompare:string1]; 
    } 
    return [string1 localizedCaseInsensitiveCompare:string2]; 
} 

// assuming anArray is array of unsorted strings 

NSArray *sortedArray; 

// sort using a selector 
sortedArray = 
    [anArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; 

// sort using a function 
BOOL reverseSort = NO; 
sortedArray = 
    [anArray sortedArrayUsingFunction:alphabeticSort context:&reverseSort]; 
+3

Chà, mã mẫu Apple cụ thể đó là khá khủng khiếp. Tại sao họ sử dụng void *, NSInteger, và int nơi nó đơn giản hơn để sử dụng một BOOL? Tại sao nó lại trả về NSInteger thay vì NSComparisonResult? Tôi chắc chắn đó là khả năng tương thích với các quyết định API trước đó, nhưng đó là frickin 'xấu xí! Tôi đề nghị sử dụng một bộ chọn (phương pháp) hơn là một chức năng để phân loại các bộ sưu tập ca cao - nó đơn giản và thanh lịch hơn. –

+0

@QuinnTaylor Tôi vừa kiểm tra và, đủ chắc chắn, tài liệu cho 'formattedArrayUsingFunction: context:' nói rằng hàm này được dự kiến ​​lấy hai 'id' và 'void *' và trả về 'NSInteger'. Trong đó, ít nhất, mẫu là chính xác. (Họ dường như đã cập nhật nó, quá - nó bây giờ hút ít hơn.) –

15

Các "cách hiệu quả nhất" để sắp xếp một tập các đối tượng khác nhau dựa trên những gì bạn thực sự có ý nghĩa. Giả thiết bình thường (mà các câu trả lời trước đó tạo ra) là một loại đối tượng một lần trong một tập hợp. Trong trường hợp này, tôi muốn nói đó là khá nhiều một toss-up giữa những gì @cobbal gợi ý và những gì bạn đã đưa ra - có lẽ giống như sau:

NSMutableArray* array = [NSMutableArray arrayWithCapacity:[set count]]; 
for (id anObject in set) 
    [array addObject:anObject]; 
[array sortUsingDescriptors:descriptors]; 

(tôi nói đó là một toss-up vì cách tiếp cận @ cobbal của tạo hai mảng autoreleased, vì vậy đôi bộ nhớ. Đây là vụn vặt cho bộ nhỏ của các đối tượng, nhưng về mặt kỹ thuật, không phải phương pháp rất hiệu quả.)

Tuy nhiên, nếu bạn đang sắp xếp các yếu tố trong các thiết lập nhiều hơn một lần (và đặc biệt là nếu nó là một điều thường xuyên) điều này chắc chắn không phải là một cách tiếp cận hiệu quả. Bạn có thể giữ một NSMutableArray xung quanh và giữ nó đồng bộ với NSSet, sau đó gọi -sortUsingDescriptors: mỗi lần, nhưng ngay cả khi mảng đã được sắp xếp, nó vẫn sẽ yêu cầu so sánh N.

Ca cao tự nó không cung cấp phương pháp hiệu quả để duy trì bộ sưu tập theo thứ tự được sắp xếp. Java có một lớp học TreeSet mà duy trì các yếu tố theo thứ tự sắp xếp bất cứ khi nào một đối tượng được chèn vào hoặc gỡ bỏ, nhưng Cocoa thì không. Chính vấn đề này đã thúc đẩy tôi phát triển một cái gì đó tương tự cho việc sử dụng của riêng tôi.

Là một phần của khung cấu trúc dữ liệu tôi được kế thừa và sửa đổi, tôi đã tạo một protocol and a few implementations for sorted sets. Bất kỳ lớp con cụ thể nào sẽ duy trì một tập hợp các đối tượng riêng biệt theo thứ tự sắp xếp. Vẫn còn có sự tinh chỉnh được thực hiện - quan trọng nhất là nó sắp xếp dựa trên kết quả của -compare: (mà mỗi đối tượng trong bộ phải thực hiện) và chưa chấp nhận một NSSortDescriptor. (Cách giải quyết là triển khai -compare: để so sánh thuộc tính quan tâm trên các đối tượng.)

Một hạn chế có thể là các lớp này (hiện tại) không phải lớp con của NS (Mutable), vì vậy nếu bạn phải vượt qua NSSet, nó sẽ không được yêu cầu. (Giao thức này có phương thức aset trả về một NSSet, dĩ nhiên là không có thứ tự.) Tôi định sửa chữa nó sớm, như tôi đã làm với các lớp con NSMutableDictionary trong khung công tác. Phản hồi chắc chắn được chào đón.:-)

0

Bạn không thể sắp xếp NSSet, bởi vì "sortedArrayUsingFunction:" thiết lập kết quả như NSArray ... Và tất cả công việc gợi ý trên chỉ với mảng :)

NSArray *myArray = [mySet sortedArrayUsingDescriptors:descriptors]; 

làm việc hoàn hảo, và không cần cách nào khác :)

8

Đối với iOS ≥ 5.0 và Mac OS X ≥ 10,7 bạn có thể trực tiếp sử dụng NSOrderedSet

+0

This doesn ' t giải quyết các câu hỏi, nơi bạn đã có một NSSet hiện có và muốn sắp xếp nó. – colincameron

0

Kể từ OS X 10.7 và iOS 5.0 có NSOrderedSet. Bạn có thể sử dụng nó để giữ cho các đối tượng trong thiết lập và giữ trật tự của họ. NSMutableOrderedSet có phương pháp phân loại. Trong một số trường hợp, điều này có thể cải thiện hiệu suất vì bạn không phải tạo đối tượng riêng biệt như NSArray để lưu trữ các mục đã sắp xếp.

Các vấn đề liên quan