在Obj-c组织一组人的最佳方法是什么?

时间:2009-12-07 07:26:57

标签: iphone objective-c data-structures

我有一个不寻常的问题,我有一份水果清单(苹果,橙子,香蕉,葡萄等)。它们可以组织成小组,例如:

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 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分: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];
    }
}

答案 2 :(得分:0)

你可以使用一个简单的CoreData解决方案,从长远来看,它可能是最简单的。对于您的方案,您可以创建两个实体,例如ItemPriceGroupItem实体可以具有name属性和一对一priceGroup关系。 PriceGroup实体可以具有description属性(尽管在您的方案中,它甚至不需要),price属性和多对多items关系。假设你设置了这两个简单的实体,并获得了一个上下文,你可以在代码中轻松创建你的关联:

- (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;
}

在这种情况下,由于没有多对多的关系,因此,如果您将来更改它,那么项目可以在多个组中(如常规价格组和销售价格组),这是确保您没有在结果中获得重复项目的必要条件。