2013-04-23 55 views
2

我想要做的是創建一個NSMutableSet,其目的是計算有多少對唯一數據。檢查一個可變集合是否包含具有相同屬性的對象

基本上,我有兩個可變數組; xCoordinatesyCoordinates以及名爲XYPoint的自定義對象。重合指數處的每個X座標和Y座標組合在笛卡爾平面上形成一個點。例如,在索引2處,可能存在xCoordinates數組中的數字4和yCoordinates數組中的數字8,從而形成點(4,8)。

現在,問題的癥結所在,我想要做的是檢查有多少個點。我打算使用NSMutableSet來做到這一點。即:

for (int i = 0; i < [xCoordinates count]; i++) { 

     XYPoint *newXY = [[XYPoint alloc] init]; 
     newXY.xCoordinate = [xCoordinates objectAtIndex:i]; 
     newXY.yCoordinate = [yCoordinates objectAtIndex:i]; 

     if ([distinct containsObject:newXY] == NO) { 

      [distinct addObject:newXY]; 

     } 

    } 

不幸的是,這是行不通的。有沒有辦法說;

if (there isn't an object in the set with an identical X coordinate property and Y coordinate property){ 

    Add one to the set; 

} 

+0

我想設置只允許唯一值,它不會在其添加重複的值。詳情請參考此文檔(https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableSet_Class/Reference/NSMutableSet.html) – 2013-04-23 06:23:05

+1

檢查此問題/答案:http ://stackoverflow.com/questions/10586218/objective-c-nsmutableset-unique-object-property – mbogh 2013-04-23 06:26:35

回答

0

關於我的頭頂,也許一些產生獨特結果的操作對於您的特定情況就足夠了(儘管可能不是最有效的解決方案)。

for (int i = 0; i < [xCoordinates count]; i++) { 

    NSString *xStr = [[xCoordinates objectAtIndex:i] stringValue]; 
    NSString *yStr = [[yCoordinates objectAtIndex:i] stringValue]; 
    NSString *coordStr = [NSString stringWithFormat:@"%@ %@",xStr,yStr]; //edited 
    if (![distinct containsObject:coordStr]) { 
     [distinct addObject:coordStr]; 
    } 
} 

我應該這樣做。您的解決方案無法正常工作,因此每次都會創建一個新對象並且不會相同。但對於NSString像上面那樣,情況並非如此。快速解決方案。

+3

有一個隱藏的bug。提示:考慮點:1,11和11,1。 – 2013-04-23 08:20:50

+0

@NikolaiRuhe:是的。沒想到這一點。更新(在%@ s之間添加一個空格)。 – Rakesh 2013-04-23 08:22:30

6

在測試成員資格時,NSSet調用使用isEqual。
isEqual:hashNSObject protocol的一部分。

如果您的XYPoint類派生自NSObject,它會繼承基於指針相等性的默認isEqual:實現。它比較內存地址以測試2個對象是否相同。
由於您的比較標準是位置,您必須在您的XYPoint類中覆蓋isEqual:,並且如果2個對象的x/y座標相同,則返回YES

也看看Collections Programming Topics。 還有一個關於equality and hashing by Mike Ash的非常詳細的帖子。

更新
作爲JeremyP在評論中指出的,你應該重寫isEqual:時總是提供hash的實現。細節在上面的Mike Ash文章中有解釋。
還有一個問題討論座標爲here on Stack Overflow的好散列函數。

+0

+1爲詳細解釋和Mike Ash鏈接。 – Rakesh 2013-04-23 08:19:01

+1

這比將座標轉換爲字符串更好。但是你也需要重寫'-hash',以使兩個相等的對象具有相同的散列。 – JeremyP 2013-04-23 09:18:49

+0

好點 - 謝謝。我更新了我的答案。 – 2013-04-23 13:25:36

2

這是Rakesh提案的增強版。

它不會遭受數字到字符串轉換的微妙之處,再加上它省略了冗餘條件。

它使用常用的NSValue點包裝來代替您的自定義類XYPoint

for (NSUInteger i = 0; i < [xCoordinates count]; ++i) { 
    CGPoint p = { [xCoordinates[i] floatValue], [yCoordinates[i] floatValue] }; 
    [distinct addObject:[NSValue valueWithCGPoint:p]]; 
} 
+0

只是一個筆記。 'valueWithCGPoint:'只適用於iOS。任何類似的可可? – Rakesh 2013-04-23 11:39:23

+0

順便說一句,這不檢查唯一性。 – Rakesh 2013-04-23 11:47:50

+1

@Rakesh OS X有'valueWithPoint:'。將CGPoints放入NSValue的通用方法在這裏描述:http://stackoverflow.com/a/2577651/104790 – 2013-04-23 14:54:02

1

擴展在weichsel's answer這是這裏最好的,一流的實施將是這個樣子:

@interface XYCoordinate : NSObject 
-(id) initWithX: (NSNumber*) newX andY: (NSNumber*) newY; 
@property (readonly, copy) NSNumber* x; 
@property (readonly, copy) NDNumber* y; 
@end 

@implementation XYCoordinate 

@synthesize x = _x; 
@synthesize y = _y; 

-(id) initWithX: (NSNumber*) newX andY: (NSNumber*) newY 
{ 
    self = [super init]; 
    if (self != nil) 
    { 
     [self setX: newX]; 
     [self setY: newY]; 
    } 
    return self; 
} 

-(BOOL) isEqual: (id) somethingElse 
{ 
    BOOL ret = NO; 
    if ([somethingElse isKindOfClass: [XYCoordinate class]]) 
    { 
     ret = [[self x] isEqual: [somethingElse x]] && [[self y] isEqual: [somethingElse y]] 
    } 
    return ret; 
} 

-(NSUInteger) hash 
{ 
    return [[self x] hash] + [[self y] hash]; // Probably a rubbish hash function, but it will do 
} 
@end 
相關問題