2009-12-07 4 views
1

J'ai un problème inhabituel où j'ai une liste de fruits (pomme, orange, banane, raisins, etc etc). Ils peuvent être organisés en petits groupes, par exemple:Quelle est la meilleure façon d'organiser un groupe de groupes dans Obj-c?

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

Chaque groupe est ensuite associé à un prix. Donc Groupe 1-> 9.99, Groupe 2-> 15.99 etc.

Et puis plus tard, quand une liste est donnée, elle doit être comparée aux groupes existants, et si aucune n'a été trouvée, créez-en une. S'il en existe un, renvoyez le prix.

Quelle est la meilleure façon de faire cela? Fondamentalement, l'association doit être un NSDictionary, mais la clé semble être un tableau. Le problème est alors, comment puis-je construire la clé quand donné une entrée? Je dois recourir à l'ordre alphabétique pour que les clés soient cohérentes? Mais alors cette approche ne serait pas trop bonne quand les noms incluent des symboles ($ apple etc).

Quelle serait votre approche?

Répondre

3

Utilisez un NSSet au lieu d'un NSArray (les ensembles sont des listes non ordonnées, et il semble que c'est ce que vous avez ici). Cependant, je ne suis pas sûr que NSDictionary utilisera la méthode [NSSet isEqualToSet:] (ou quel que soit son nom) plutôt que l'égalité de pointeur lors de la détermination des clés, vous devrez donc implémenter votre propre méthode de vérification des clés.

1

On dirait que vous pouvez utiliser NSSet comme la clé de 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); 

Sorties:

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 

Une autre façon est d'utiliser NSMutableDictionary qui détient plusieurs de NSSet des articles et des prix comme une clé, cependant, il est noté que cela ne fonctionnera pas si le prix n'est pas unique.

Vous vérifiez manuellement si l'ensemble est dans le dictionnaire en itérant sur les éléments et pour chaque ensemble en utilisant isEqualToSet: - à moins que n'importe qui peut trouver une meilleure façon.

Si si elle ne vous pouvez l'insérer est de retourner le prix (clé) avec un prix, les parties principales:

@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

Mais que faire si le prix n'était pas unique? – erotsppa

+0

Puis stocker les objets dans NSMutableSets, et au lieu d'ajouter un nouvel ensemble avec le même prix vérifier pour voir si un ensemble existe déjà avec ce prix, et ajouter des objets dans ce cas. –

+0

Tout ce que je peux penser au cas où le prix n'est pas unique est de créer un enregistrement, soit une classe personnalisée ou NSDictionary de NSSet, la liste des éléments, et le prix, et pour la clé que vous utiliseriez quelque chose comme id unique (int). – stefanB

0

Vous pouvez utiliser un simple La solution CoreData pour cela, et à long terme, ce sera probablement le plus facile. Pour votre scénario, vous pouvez créer deux entités, disons Item et PriceGroup. L'entité Item peut avoir un attribut name et une relation un-un priceGroup. L'entité PriceGroup peut avoir un attribut description (bien que, dans votre scénario, il n'en ait même pas besoin), un attribut price et une relation items.En supposant que vous configurez ces deux entités simples, et obtenez un contexte, vous pouvez facilement créer vos associations comme si dans le code:

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

Vous auriez maintenant tous vos produits associés à votre groupe de prix dans votre contexte d'objet géré . Cela signifie que vous pouvez faire toutes sortes de requêtes sur eux, les trier facilement, etc

Comme un autre exemple, voici comment vous pourriez obtenir tous les articles dont le prix de groupe est plus de 9,99 $, mais pas dans un groupe spécifique (disons le $ 15,99 vente groupe de prix):

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

dans ce cas, cependant, car il n'y a pas beaucoup à de nombreuses relations, ayant l'ensemble est inutile, si vous avez changé à l'avenir de sorte qu'un élément pourrait être plusieurs groupes (comme un groupe de prix régulier et un groupe de prix de vente), cela serait nécessaire pour s'assurer que vous n'avez pas eu d'articles en double dans votre résultat.

Questions connexes