简体   繁体   中英

Update a value in a list of dictionaries in python based on a condition based on the value of another key in that dictionary

Given a list of dictionaries:

the_list = [{k1:v1,k2:v2}, {k1:v3, k3:v4}, {k1:v5,k2:v6},{k3:v7}]

How can I update the value for k2 based on a condition based on the value of k1 ?

I would come up with this solution but it doesn't feel Pythonic. Better solutions anyone?

for item in the_list:
  if set([k1,k2]) <= item.keys():
    #cond evaluates to True or False
    if cond(item[k1]):
      item.update({k2:newvalue})

Maybe this can be done better with a map or lambda expression?

This is the simplest code I came up with to perform the same operation:

my_list = [{k1:v1,k2:v2}, {k1:v3, k3:v4}, {k1:v5,k2:v6},{k3:v7}]
for my_dict in my_list:
    if all (k in my_dict for k in ("k1", "k2")):
        if cond(my_dict[k1]):
            my_dict[k2] = newvalue # possibly pre-determined 

Depending on the way cond evaluates the value of k1 and/or newvalue is generated, the code might be further more "Pythonized".

well in python dir(dict) shows us available methods for dictionary, and "somemethod" in dir(dict) shows us if somemethod is available in sed data type. SO if we factor it in our problem we can se that in :

py.2.7->

['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__',\
 '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__',\
 '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__',\
 '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__',\
 '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems',\
 'iterkeys', 'itervalues','keys', 'pop', 'popitem', 'setdefault', 'update', 'values', \
'viewitems', 'viewkeys', 'viewvalues']

py.3.5 ->

['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__',\
 '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__',\
 '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__',\
 '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__',\
 '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems',\
 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values',\
 'viewitems', 'viewkeys', 'viewvalues']

Now we can see several things here, pop , popitem , has_key ,'get', and since dictionary in python is not ordered or sorted ( it prints it out as it goes ) we can also use update .

So first we need to transverse trough list of dictionaries and condition trough items, depending on size of your dictionary map or dictionary comprehension could do the trick or just dict.items() which returns list of tuples. so

def duDict(dictionary,codnitionElement,keyInQuesiton):
    el = dictionary.pop(keyInQuesiton) #similar as list.pop
    if condition(dictionary.get(codnitionElement)):
       el = something
       dictionary.update({keyInQuesiton:el })
    else:pass
    return dictionary

then something along the lines

condDict = lambda dict: duDict(dict,predefinedCondition,forKey)
map( condDict , listOfDicts )

Hope this helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM