a = {
    'user': {
        'username': 'mic_jack',    
        'name': {
            'first': 'Micheal',
            'last': 'Jackson'
        },
        'email': 'micheal@domain.com',

        #...
        #... Infinite level of another nested dict
    }     
}

str_key_1 = 'user.username=john'
str_key_2 = 'user.name.last=henry'
#...
#str_key_n = 'user.level2.level3...leveln=XXX'

Betrachten wir diesen 'str_key'-String, der zu einer unendlichen Anzahl von Punkten / Ebenen passt.

Erwartete Ausgabe:

a = {
    'user': {
        'username': 'john',     # username, should be replace    
        'name': {
            'first': 'Micheal',
            'last': 'henry'     # lastname, should be replace 
        },
        'email': 'micheal@domain.com',

        ...
        ... # Infinite level of another nested dict
    }     
}

Ich erwarte die Antworten für das Anwenden der 'n'-Ebene der verschachtelten Schlüsselzeichenfolge, anstatt sie einfach statisch durch a['user']['username'] = 'John' zu ersetzen. Die Antworten müssen für eine beliebige Anzahl von 'gepunkteten' Zeichenfolgenwerten funktionieren.

Danke im Voraus!

1
Jai K 18 Jän. 2019 im 16:13

4 Antworten

Beste Antwort

Es gibt drei Schritte:

  1. Trennen Sie die Schlüssel-Wert-Paar-Zeichenfolge in einen vollständig qualifizierten Schlüssel und Wert.
  2. Teilen Sie den Schlüssel in Pfadkomponenten auf.
  3. Durchsuchen Sie das Wörterbuch, um den relevanten Wert für die Aktualisierung zu finden.

Hier ist ein Beispiel, wie der Code aussehen könnte:

# Split by the delimiter, making sure to split once only
# to prevent splitting when the delimiter appears in the value
key, value = str_key_n.split("=", 1)

# Break the dot-joined key into parts that form a path
key_parts = key.split(".")

# The last part is required to update the dictionary
last_part = key_parts.pop()

# Traverse the dictionary using the parts
current = a
while key_parts:
  current = current[key_parts.pop(0)]

# Update the value
current[last_part] = value
1
wilsonzlin 18 Jän. 2019 im 13:41
str_key_1 = 'user.username=john'
str_key_2 = 'user.name.last=henry'

a = {
    'user': {
        'username': 'mic_jack',    
        'name': {
            'first': 'Micheal',
            'last': 'Jackson'
        },
        'email': 'micheal@domain.com',

        #...
        #... Infinite level of another nested dict
    }     
}

def MutateDict(key):
    strkey, strval = key.split('=')[0], key.split('=')[1]
    strkeys = strkey.split('.')
    print("strkeys = " ,strkeys)
    target = a
    k = ""
    for k in strkeys:
        print(target.keys())
        if k in target.keys():
            prevTarget = target
            target = target[k]
        else:
            print ("Invalid key specified")
            return
    prevTarget[k] = strval


MutateDict(str_key_1)

print(a)

MutateDict(str_key_2)

print(a)
0
Faisal 21 Jän. 2019 im 09:25

Wenn Sie mit exec () einverstanden sind und Ihre str_key (s) ändern, können Sie Folgendes tun:

def get_keys_value(string):
    keys, value = string.split("=")
    return keys, value

def get_exec_string(dict_name, keys):
    exec_string = dict_name
    for key in keys.split("."):
        exec_string = exec_string + "[" + key + "]"
    exec_string = exec_string + "=" + "value"
    return exec_string

str_key_1 = "'user'.'username'=john"
str_key_2 = "'user'.'name'.'last'=henry"
str_key_list = [str_key_1, str_key_2]

for str_key in str_key_list:
    keys, value = get_keys_value(str_key) # split into key-string and value
    exec_string = get_exec_string("a", keys) # extract keys from key-string 
    exec(exec_string)

print(a)
# prints {'user': {'email': 'micheal@domain.com', 'name': {'last': 'henry', 'first': 'Micheal'}, 'username': 'john'}}
0
Sanchit Mathew 18 Jän. 2019 im 14:55

Ich würde eine rekursive Funktion verwenden, um dies zu erreichen, vorausgesetzt, Ihre Schlüsselwertzeichenfolgen sind alle gültig:

def assign_value(sample_dict, str_keys, value):
  access_key = str_keys[0]

  if len(str_keys) == 1:
    sample_dict[access_key] = value
  else:
    sample_dict[access_key] = assign_value(sample_dict[access_key], str_keys[1:], value)

  return sample_dict

Die Idee ist, Ihr dict zu durchlaufen, bis Sie das niedrigste key erreichen, und dann weisen wir diesem letzten Schlüssel unseren neuen Wert zu.

if __name__ == "__main__":
  sample_dict = {
      'user': {
          'username': 'mic_jack',    
          'name': {
              'first': 'Micheal',
              'last': 'Jackson'
          },
          'email': 'micheal@domain.com'
      }     
  }

  str_key_1 = 'user.username=john'
  str_keys_1, value_1 = str_key_1.split('=')
  sample_dict = assign_value(sample_dict, str_keys_1.split('.'), value_1)

  print("result: {} ".format(sample_dict))


  str_key_2 = 'user.name.last=henry'
  str_keys_2, value_2 = str_key_2.split('=')
  sample_dict = assign_value(sample_dict, str_keys_2.split('.'), value_2)

  print("result: {}".format(sample_dict))

Um assign_value zu verwenden, müssten Sie Ihren ursprünglichen Schlüssel wie oben gezeigt in die Schlüssel und Wert aufteilen.

0
fixatd 18 Jän. 2019 im 14:03