2011-02-02 11 views
9

Tengo un NSMutableDictionary. Tengo que renombrar dinámicamente cualquier Key en el diccionario a un nuevo valor, en mi código ... No puedo encontrar ninguna API incorporada para hacer esto ...¿Cómo cambiar el nombre de una clave en NSMutableDictionary?

¿Cómo puedo hacer esto? ¿Hay alguna API incorporada disponible para hacer esto?

Gracias a todos ..

+0

Es una opción para copiar el valor a cabo, a continuación, crear una nueva clave con el nombre deseado? – Jumhyn

+0

No puedo editar directamente una clave existente? – EmptyStack

Respuesta

35
// assumes that olkdey and newkey won't be the same; they can't as 
// constants... but... 
[dict setObject: [dict objectForKey: @"oldkey"] forKey: @"newkey"]; 
[dict removeObjectForKey: @"oldkey"]; 

Piense en lo "editando directamente una clave existentes" significa. Un diccionario es un hash; comprime los contenidos de las claves para encontrar un valor.

¿Qué sucede si cambia el contenido de una clave? La clave debería volver a procesarse (y las estructuras internas del diccionario se reequilibrarían) o el valor ya no se podría recuperar.

¿Por qué quiere editar el contenido de una clave en primer lugar? Es decir. ¿Qué problema resuelve eso que el anterior no lo hace?

+0

Gracias .. Esto está bien ... ¿No puedo editar directamente una clave existente? – EmptyStack

+0

Mmm ... Nada específico ... Solo esperaba una forma directa de editar la clave ... Eso es todo ... Gracias, amigo ... – EmptyStack

+0

Gracias a @bbum, esto funcionó también para un NSUserdefault. – Douglas

9

Esto debería funcionar:

- (void) renameKey:(id<NSCopying>)oldKey toKey:(id<NSCopying>)newKey{ 
    NSObject *object = [dictionary objectForKey:oldKey]; 
    [object retain]; 
    [dictionary removeObjectForKey:oldKey]; 
    [dictionary setObject:object forKey:newKey]; 
    [object release]; 
} 

Esto hace exactamente lo mismo que la respuesta de bbum pero, si se quita la llave antigua primero (como en este ejemplo), entonces usted tiene que retener el objeto temporalmente de lo contrario podría obtener desasignado en el camino;)

Conclusión: A menos que necesite eliminar explícitamente la clave anterior, primero haga como bbum.

+1

Esto también es significativamente más defensivo y de propósito general; si oldKey y newKey son la misma cadena, todavía funciona (aunque hace un trabajo extra). – bbum

3

Did que ha intentado este enlace

Can I change an NSDictionaries key?

+0

Hmm .. Gotcha ... Creé un duplicado ... :) – EmptyStack

+0

No es exactamente un duplicado, ya que esa pregunta se trata de mutar la clave que está en el diccionario, mientras que su pregunta, @Simon, trata de mutar el diccionario en sí. El mismo resultado final, pero examinando diferentes caminos hacia él. –

+2

@Peter Hosey: Muy bien ... Gracias .. – EmptyStack

5
@interface NSMutableDictionary (KAKeyRenaming) 
- (void)ka_replaceKey:(id)oldKey withKey:(id)newKey; 
@end 

@implementation NSMutableDictionary (KAKeyRenaming) 
- (void)ka_replaceKey:(id)oldKey withKey:(id)newKey 
{ 
    id value = [self objectForKey:oldKey]; 
    if (value) { 
     [self setObject:value forKey:newKey]; 
     [self removeObjectForKey:oldKey]; 
    } 
} 
@end 

Esto también maneja el caso en que el diccionario no tiene un valor para la clave muy bien.

+0

Hmm .. Mejor ... – EmptyStack

+1

Otra buena solución; pero prefija esos métodos con algo que no sea genérico y posiblemente colisione con alguna adición futura al marco, si alguna vez hubo uno ... – bbum

+1

@bbum es correcto: el prefijo de clases y protocolos personalizados debe considerarse un requisito. Editado por el bien de la perfección. – Costique

0

Tengo que navegar por un objeto de respuesta JSON completo que contiene campos, sub-diccionarios y sub-arrays. Todo porque uno de los campos JSON se llama "return", que es una palabra reservada de iOS, por lo que no se puede usar con el JSONModel Cocoa Pod. Aquí está el código:

+ (id) sanitizeJSON:(id) dictIn { 
if (dictIn) //check not null 
{ 
    // if it's a dictionary item 
    if ([dictIn isKindOfClass:[NSDictionary class]]) 
    { 
     NSMutableDictionary *dictOut = [dictIn mutableCopy]; 
     // Do the fix replace "return" with "not_return" 
     if ([dictOut objectForKey: @"return"]) 
     {[dictOut setObject: [dictIn objectForKey: @"return"] forKey: @"not_return"]; 
     [dictOut removeObjectForKey: @"return"];} 

     // Continue the recursive walk through 
     NSArray*keys=[dictOut allKeys]; //get all the keys 
     for (int n=0;n<keys.count;n++) 
     { 
      NSString *key = [keys objectAtIndex:n]; 
      //NSLog(@"key=%@ value=%@", key, [dictOut objectForKey:key]); 
      if (([[dictOut objectForKey:key] isKindOfClass:[NSDictionary class]]) || ([[dictOut objectForKey:key] isKindOfClass:[NSArray class]])) 
      { 
       // recursive call 
       id sanitizedObject = [self sanitizeJSON:[dictOut objectForKey:key]]; 
       [dictOut removeObjectForKey: key]; 
       [dictOut setObject:sanitizedObject forKey:key]; 
       // replace returned (poss modified) item with this one 
      } 
     } 
     return dictOut; //return dict 
    } 
    else if ([dictIn isKindOfClass:[NSArray class]]) //Or if it's an array item 
    { 

     NSMutableArray *tempArray = [dictIn mutableCopy]; 
     // Do the recursive walk across the array 
     for (int n=0;n< tempArray.count; n++) 
     { 
      // if array item is dictionary 
      if (([[tempArray objectAtIndex:n] isKindOfClass:[NSDictionary class]]) || ([[tempArray objectAtIndex:n] isKindOfClass:[NSArray class]])) 
      { 
       // recursive call 
       id sanitizedObject = [self sanitizeJSON:[tempArray objectAtIndex:n]]; 
       // replace with the possibly modified item 
       [tempArray replaceObjectAtIndex:n withObject:sanitizedObject]; 
      } 
     } 
     return tempArray; //return array 
    } 
    return dictIn; //Not nil or dict or array 
} 
else 
    return dictIn; //return nil 
} 
Cuestiones relacionadas