2010-10-24 41 views
11

Tôi có một mảng với các đối tượng tùy chỉnh. Mỗi mục mảng có một trường có tên là "name". Bây giờ tôi muốn loại bỏ các mục trùng lặp dựa trên giá trị tên này.xóa các bản sao khỏi mảng trong mục tiêu c

Tôi nên làm thế nào để đạt được điều này.

Xin cảm ơn trước.

+0

Are các mục trong một container Objective-C như NSArray, hoặc C/C++ (ví dụ, std :: vector hoặc một mảng C)? –

+2

lý do tại sao thẻ C? –

+0

xin lỗi đã xóa thẻ, mảng c mục tiêu của nó bằng các đối tượng tùy chỉnh ... "name" là một trong các biến thành viên của nó, tôi muốn lọc dựa trên giá trị "tên" này. –

Trả lời

9

Bạn có thể phải thực sự viết phương pháp lọc này tự hỏi:

@interface NSArray (CustomFiltering) 
@end 

@implementation NSArray (CustomFiltering) 

- (NSArray *) filterObjectsByKey:(NSString *) key { 
    NSMutableSet *tempValues = [[NSMutableSet alloc] init]; 
    NSMutableArray *ret = [NSMutableArray array]; 
    for(id obj in self) { 
     if(! [tempValues containsObject:[obj valueForKey:key]]) { 
      [tempValues addObject:[obj valueForKey:key]]; 
      [ret addObject:obj]; 
     } 
    } 
    [tempValues release]; 
    return ret; 
} 

@end 
+0

mảng không phải là mảng của nó là mảng đối tượng tùy chỉnh .... với tên chuỗi là thuộc tính ... Tôi muốn lọc dựa vào tên tài sản này –

+0

Liệu người chăm sóc downvoter có nhận xét không? –

+0

@Jacob: Đã viết câu trả lời của tôi giống như bạn đã chỉnh sửa. Bạn thực sự nên sử dụng một 'NSMutableSet' thay vì một' NSMutableArray' để tra cứu, hiệu suất tăng từ một tra cứu hash khá tốt hơn so với tìm kiếm tuyến tính. – PeyloW

27

Tôi không biết về bất kỳ cách tiêu chuẩn để làm việc này được cung cấp bởi các khuôn khổ. Vì vậy, bạn sẽ phải làm điều đó trong mã. Một cái gì đó như thế này nên được doable:

NSArray* originalArray = ... // However you fetch it 
NSMutableSet* existingNames = [NSMutableSet set]; 
NSMutableArray* filteredArray = [NSMutableArray array]; 
for (id object in originalArray) { 
    if (![existingNames containsObject:[object name]]) { 
     [existingNames addObject:[object name]]; 
     [filteredArray addObject:object]; 
    } 
} 
+0

Cảm ơn PeyloW câu trả lời của bạn đã đúng ngay tại chỗ ... ngón tay cái ... Tôi muốn bạn may mắn nhất trong nỗ lực của bạn .... –

+2

Không nên là [object objectForKey: @ "name"]; trong vòng lặp đó? –

+0

không có Skeater. Đó là cho một NSDictionary. –

1

Nếu bạn muốn tùy chỉnh NSObject lớp con của bạn được coi là bình đẳng khi tên của họ đều bình đẳng, bạn có thể thực hiện isEqual:hash. Điều này sẽ cho phép bạn thêm các đối tượng vào một số NSSet/NSMutableSet (một tập hợp các đối tượng riêng biệt).

Sau đó, bạn có thể dễ dàng tạo một sắp xếp NSArray bằng cách sử dụng phương pháp NSSet 's sortedArrayUsingDescriptors:.

MikeAsh đã viết một mảnh khá vững chắc về việc thực hiện bình đẳng tùy chỉnh: Friday Q&A 2010-06-18: Implementing Equality and Hashing

1

Nếu bạn đang lo lắng về thứ tự

NSArray * newArray = 
     [[NSOrderedSet orderedSetWithArray:oldArray] array]; **// iOS 5.0 and later** 
2

tôi sẽ có được pháo phòng không cho điều này ...

Bạn có thể chuyển đổi mảng của bạn thành một từ điển. Bạn không chắc chắn hiệu quả của điều này, phụ thuộc vào việc thực hiện và so sánh cuộc gọi, nhưng nó sử dụng một bản đồ băm.

//Get unique entries 
NSArray *myArray = @[@"Hello", @"World", @"Hello"]; 
NSDictionary *uniq = [NSDictionary dictionaryWithObjects:myArray forKeys:myArray]; 
NSLog(@"%@", uniq.allKeys); 

* Lưu ý, điều này có thể thay đổi thứ tự của mảng của bạn.

+0

Hehehehe I LOVE this! –

+0

Chỉnh sửa: tôi cũng đã dành 15 phút cuối cùng để sửa lỗi trong mã của mình. Sử dụng phương pháp NSDictionary này sẽ KHÔNG giữ thứ tự của mảng của bạn. Tất cả các vật phẩm của tôi đều bị xáo trộn. Đó là những gì tôi nhận được để sử dụng hacky wordk-xung quanh nơi OP prefaces "Tôi sẽ nhận được flak cho điều này ..." lol –

7

Tôi biết đây là một câu hỏi cũ nhưng đây là một khả năng khác, tùy thuộc vào những gì bạn cần.

Apple cung cấp cách để thực hiện việc này - Key-Value Coding Collection Operators.

Toán tử đối tượng cho phép bạn hành động trên bộ sưu tập. Trong trường hợp này, bạn muốn:

@distinctUnionOfObjects

Nhà điều hành @distinctUnionOfObjects trả về một mảng chứa các đối tượng khác nhau trong các tài sản theo quy định của con đường chính ở bên phải của các nhà điều hành.

NSArray *distinctArray = [arrayWithDuplicatesvalueForKeyPath:@"@distinctUnionOfObjects.name"];

Trong trường hợp của bạn, tuy nhiên, bạn muốn toàn bộ đối tượng. Vì vậy, những gì bạn phải làm là hai lần: 1) Sử dụng @distinctUnionOfArrays để thay thế. Ví dụ. Nếu bạn có các đối tượng tùy chỉnh này đến từ các bộ sưu tập khác, hãy sử dụng @distinctUnionOfArray.myCollectionOfObjects 2) Thực hiện isEqual: trên các đối tượng đó để trả lại nếu chúng.tên của đều bình đẳng

0

Thực hiện isEqual để làm cho đối tượng của bạn có thể so sánh:

@interface SomeObject (Equality) 
@end 

@implementation SomeObject (Equality) 

- (BOOL)isEqual:(SomeObject*)other 
{ 
    return self.hash == other.hash; 
} 

- (NSUInteger)hash 
{ 
    return self.name;///your case 
} 

@end 

Làm thế nào để sử dụng:

- (NSArray*)distinctObjectsFromArray:(NSArray*)array 
{ 
    return [array valueForKeyPath:@"@distinctUnionOfObjects.self"]; 
} 
0

Nó là khá đơn giản trong một dòng

NSArray *duplicateList = ... 

Nếu bạn không quan tâm đến thứ tự các yếu tố sau đó (không có thứ tự)

NSArray *withoutDUP1 = [[NSSet setWithArray:duplicateList] allObjects]; 

Giữ các yếu tố theo thứ tự sau đó (ra lệnh)

NSArray *withoutDUP2 = [[NSOrderedSet orderedSetWithArray:duplicateList] array]; 
+0

Nhưng làm thế nào là lọc mã của bạn dựa trên "tên" trường? – Satyam

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