2009-12-07 138 views
1

我有一个不寻常的问题,我有一个水果名单(苹果,橙,香蕉,葡萄等)。它们可以组织成小组,例如:在Obj-c中组织一组的最佳方式是什么?

Group 1: apple, green_apple, pineapple 
Group 2: grapes, banana, strawberries, apple 
Group 3: orange, grapes, green_apple 

然后,每个组都与价格相关联。因此,组1 - > 9.99,组2 - > 15.99等

然后稍后当给出一个列表,他们需要匹配现有的组,如果没有找到,创建一个。如果存在,则返回价格。

这样做的最好方法是什么?基本上这个关联需要是一个NSDictionary,但是关键看起来应该是一个数组。那么问题是,如何在输入一些信息时构造密钥?我必须求助于按字母顺序排列键,以使键保持一致?但是当名称包含符号($ apple等)时,这种方法不会太好。

你的方法是什么?

回答

3

使用NSSet而不是NSArray(集合是无序列表,它听起来就是你在这里得到的)。但是,我不确定NSDictionary在确定密钥时将使用[NSSet isEqualToSet:](或其他所谓的方法)方法而不是指针相等,因此您可能必须实现自己的密钥检查方法。

1

好像你可以使用NSSet中作为关键的NSDictionary:

NSMutableDictionary * dict = [NSMutableDictionary dictionary]; 

NSSet * set; 
set = [NSSet setWithObjects:@"a", @"b", @"c", @"d", nil]; 
[dict setObject:@"1" forKey:set]; 

set = [NSSet setWithObjects:@"b", @"c", @"d", @"e", nil]; 
[dict setObject:@"2" forKey:set]; 

id key; 
NSEnumerator * enumerator = [dict keyEnumerator]; 
while ((key = [enumerator nextObject])) 
    NSLog(@"%@ : %@", key, [dict objectForKey:key]); 

set = [NSSet setWithObjects:@"c", @"b", @"e", @"d", nil]; 
NSString * value = [dict objectForKey:set]; 
NSLog(@"set: %@ : key: %@", set, value); 

输出:

2009-12-08 15:42:17.885 x[4989] (d, e, b, c) : 2 
2009-12-08 15:42:17.887 x[4989] (d, a, b, c) : 1 
2009-12-08 15:42:17.887 x[4989] set: (d, e, b, c) : key: 2 

另一种方法是使用NSMutableDictionary持有多个NSSet“项目和价格第作为一个关键,但是注意到,如果价格不是唯一的,这将不起作用。

您可以手动检查集合是否在字典中,通过遍历项目和每个集合使用isEqualToSet: - 除非任何人都能想出更好的方法。

如果您返回的价格(关键),如果它不是你可以用一个价格,主要部件插入:

@interface ShoppingList : NSObject 
{ 
    NSMutableDictionary * shoppingList; 
} 

- (void)setList:(NSSet*)aList 
     forPrice:(double)aPrice 
{ 
    [shoppingList setObject:aList forKey:[NSNumber numberWithDouble:aPrice]]; 
} 

- (double)priceForList:(NSSet*)aList 
{ 
    id key; 
    NSEnumerator * enumerator = [shoppingList keyEnumerator]; 
    while ((key = [enumerator nextObject])) 
    { 
     NSSet * list = [shoppingList objectForKey:key]; 

     if ([aList isEqualToSet:list]) 
     { 
      return [(NSNumber*)key doubleValue]; 
     } 
    } 

    return 0.0; 
} 

{ 
    ShoppingList * shoppingList = [[ShoppingList alloc] init]; 

    NSSet * list; 
    double price = 0.0; 

    list = 
     [NSSet setWithObjects:@"apple",@"green_apple",@"pineapple",nil]; 
    [shoppingList setList:list forPrice:9.99]; 

    list = 
     [NSSet setWithObjects:@"grapes",@"banana",@"strawberries",@"apple",nil]; 
    [shoppingList setList:list forPrice:15.99]; 

    list = 
    [NSSet setWithObjects:@"orange",@"grapes",@"green_apple",nil]; 
    [shoppingList setList:list forPrice:7.50]; 

    // searching for this 
    list = 
     [NSSet setWithObjects:@"grapes",@"banana",@"strawberries",@"apple",nil]; 

    price = [shoppingList priceForList:list]; 
    if (price != 0.0) 
    { 
     NSLog(@"price: %.2f, for pricelist: %@", price, list); 
    } 
    else 
    { 
     NSLog(@"shopping list not found: %@", list); 
     [shoppingList setList:list forPrice:15.99]; 
    } 
} 
+0

但是如果价格不是唯一的呢? – erotsppa 2009-12-07 13:59:46

+0

然后将对象存储在NSMutableSets中,而不是使用相同的价格检查添加新的集合,以查看是否存在具有该价格的集合,并在其中添加对象。 – 2009-12-07 17:04:25

+0

所有我能想到的情况下,价格不唯一的情况是创建记录,无论是NSSet的自定义类或NSDictionary,项目列表和价格,并且对于密钥,您可以使用类似唯一id(int)的内容。 – stefanB 2009-12-07 19:57:32

0

您可以使用简单e CoreData解决方案,从长远来看,它可能是最简单的。对于你的场景,你可以创建两个实体,比如说ItemPriceGroupItem实体可以具有name属性和一对一的关系。 PriceGroup实体可能具有description属性(尽管在您的方案中它甚至不需要该属性),price属性和多对多关系。假设你建立这两个,简单的实体,并得到一个情况下,你可以轻松地创建社团,像这样的代码:

- (void)createGroup:(NSNumber*)price withProducts:(NSSet*)productNames 
{ 
    // assume context exists and was retrieved from somewhere 
    NSManagedObject* priceGroup = [NSEntityDescription insertNewObjectForEntityForName:@"PriceGroup" inManagedObjectContext:context]; 
    [priceGroup setValue:price forKey:@"price"]; 

    for(NSString* productName in productNames) { 
    NSManagedObject* product = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:context]; 
    [product setValue:productName forKey:@"name"]; 
    [product setValue:priceGroup forKey:@"priceGroup"]; 
    } 
} 

现在你会与你的价格组相关联的所有产品在你的管理对象上下文。这意味着您可以对它们进行各种查询,轻松地对它们进行排序等。

作为另一个示例,以下是如何获取组价格超过9.99美元的所有商品,而不是某些特定组(例如, $ 15.99售价组):

- (NSSet*)itemsAsDescribed 
{ 
    // Get this from somewhere 
    NSManagedObjectContext* context = /* get this or set this */ 
    NSManagedObject* exclusionGroup = /* get this or set this */ 
    NSFetchRequest* request = [[[NSFetchRequest alloc] init] autorelease]; 
    NSPredicate* predicate = [NSPredicate predicateWithFormat:@"priceGroup.price >= 9.99 AND NOT SELF in %@", [exclusionGroup valueForKey:@"items"]]; 
    [request setEntity:[NSEntityDescription entityForName:@"Item" inManagedObjectContext:context]]; 
    [request setPredicate:predicate]; 
    NSError* error = nil; 
    NSSet* results = nil; 
    NSArray* array = [context executeFetchRequest:request error:&error]; 
    if(!array) { 
    // handle the error 
    } else { 
    results = [NSSet setWithArray:array]; 
    } 
    return results; 
} 

在这种情况下,由于不会有太多的一对多的关系,具有集是不必要的,但是,如果你在未来改变它,这样一个项目可以在多个组(如常规价格组和销售价格组),这对于确保您的结果中没有重复项目是必要的。

相关问题