Python List Comprehesion conversion - python

So I have a script like this
for key, Value in mydictionary.iteritems():
if 'Mammal' in Value[1]:
#because the value is a list of 2 items and I want to get at the second one
Value[1] = Value[1].strip('Mammal')
This code effectively removes Mammal from the beginning of the second item in the Value list. Now I want to make this nicer python looking with list comprehension so I came up with this but obviously is wrong.... Any help?
Value[1] = [Value[1].strip('Mammal') for Key, Value in mydictionary.iteritems() if 'Mammal' in Value[1] ]
Also, on the same lines, a list comprehension to list all the keys in this dictionary. I am having a hard time coming up with that one.
I came up with:
for key, Value in mydictionary.iteritems():
Templist.append(key)
but as a list comprehension I am thinking....but it doesn't work :(
alist = [key for Key, Value in mydictionary.iteritems()]

mydictionary = {
1: [4, "ABC Mammal"],
2: [8, "Mammal 123"],
3: [15, "Bird (Not a Mammal)"]
}
mydictionary = {key: ([value[0], value[1].strip('Mammal')] if 'Mammal' in value[1] else value) for key, value in mydictionary.iteritems()}
print mydictionary
Output:
{1: [4, 'ABC '], 2: [8, ' 123'], 3: [15, 'Bird (Not a Mammal)']}
Although I wouldn't call this objectively "nicer looking", so the iterative method may be preferable.

List comprehension creates a new list
If you were able to use strip(), then Value[1] is a string - not a list
You may do 2nd part just with dictionary method keys() - both your attempts are redundant.
alist = mydictionary.keys()

mydict = {'a':['Mammal','BC','CD'],
'b':['AB','XY','YZ'],
'c':['Mammal','GG','FD'],}
print [x for x,y in mydict.items() if y[0]=='Mammal']

You should not use a list comprehension solely to create side effects. You can, but it is considered bad practice, and you should stick with the for loop.
Anyway, since you are working with a dictionary, you may be looking for a dict comprehension:
mydictionary = {'foo': ['unknown', 'Mammal is great'],
'bar': ['something', 'dont touch me']}
mydictionary = {k: [a, b.replace('Mammal', '', 1)] for k, [a, b] in mydictionary.iteritems() if b.startswith('Mammal')}
Also note that using if you use dict comprehension, you create a new dictionary instead of replacing the values in your old one.
...
Value[1] = Value[1].strip('Mammal')
...
This code effectively removes Mammal from the beginning of the second item in the Value list.
No, it does not. It replaces all occurrences of M, a, m and l from the beginning and the end of that item. Better use the replace method to replace the first occurrence of Mammal with an empty string.
alist = [key for Key, Value in mydictionary.iteritems()]
You have a typo here. It should read:
alist = [key for key, value in mydictionary.iteritems()]
or just
alist = mydictionary.keys()

Related

Replace elements in a nested dict with the appropriate in a list

I have such following a dict and a list.
mylist= ['1H1.PyModule.md',
'1H2.Class.md',
'1H3.MetaObject.md',
'2B1D0.Data.md',
'2B1D1.Primitive.md',
'2B1D2.Operator.md',
'2B2D3.Container.md',
'2B2S0.Function.md',
'2B2S0.Statemment.md',
'2B2S1.Controlled_Loop.md',
'2B2S2.Conditions.md',
'2B2S3.Except.md',
...
]
mydict = {'Body': {'Data': ['1.primitive', '2.operator', '3.container'],
'Statement': ['0.function', '1.controlled_loop', '2.condition', '3.except']},
'Header': ['1.Modle', '2.Class', '3.Object'],
...}
I attempt to repalce the strings in mydict with the appropriate in mylist
I can figure out '2B1D0.Data.md' has the shortest length,
So I slice the keyward 'Data'
In [82]: '2B1D0.Data.md'[-7:-3]
Out[82]: 'Data'
The dict has both a nested list and nested dict.
So I write a iteration function with type checking
if an item's value isinstance(value,list), renew that value,
if an item's value isinstance(value, dict),call the function replace_ele()to continue.
I name string in mylist as str_of_list,
while string in mydict as str_of_dict for readable concerns.
#replace one string in mydict
def replace_ele(mydict, str_of_list):
for key, value in mydict.items():
if isinstance(value, list): #type checking
for str_of_dict in value:
#replace str_of_dict with str_of_list
if str_of_list[-7:-3].lower() == str_of_dict[-4:]: #[-7:-3] the shortest length
value.remove(str_of_dict)
value.append(str_of_list)
value.sort()
mydict[key] = value
#iteration if a dict
if isinstance(value, dict):
replace_ele(value,str_of_list)
for str_of_list in mylist:
replace_ele(mydict, str_of_list)
Then running and outputs:
Out[117]:
{'Body': {'Data': ['2B1D1.Primitive.md',
'2B1D2.Operator.md',
'2B2D3.Container.md'],
'Statement': ['2B2S0.Function.md',
'2B2S0.Function.md',
'2B2S1.Controlled_Loop.md',
'2B2S3.Except.md']},
'Header': ['1.Modle', '1H2.Class.md', '1H3.MetaObject.md']
....}
I assume that such a problem can be solved with less codes.
However, I cannot find that solution with the limited knowledge.
How to accomplish it elegantly?
My suggestion is that you create a function to reduce element of mylist and elements in lists of mydict values to the same format:
For example, you can split by '.' character, take the second field, convert it to lower case:
def f(s):
return s.split('.')[1].lower()
E.g.:
>>> f('2B2S1.Controlled_Loop.md')
'controlled_loop'
>>> f('1.controlled_loop')
'controlled_loop'
Now, from mylist create a dict to hold replacements:
mylist_repl={f(x): x for x in mylist}
i.e. mylist_repl contains key: value items such as 'metaobject': '1H3.MetaObject.md'.
With dict mylist_repl and function f, it is easy to transform a list from mydict to the desired value, example:
>>> [mylist_repl[f(x)] for x in ['1.primitive', '2.operator', '3.container']]
['2B1D1.Primitive.md', '2B1D2.Operator.md', '2B2D3.Container.md']
Also note that this dictionary lookup is more efficient (i.e.: faster) than a nested for loop!
If you have different replacement logic, you probably only need to change how f maps items from two different sets to a common key.

List comprehensions - extracting values from a dictionary in a dictionary

I'm trying to get a list of names from a dictionary of dictionaries...
list = {'1':{'name':'fred'}, '2':{'name':'john'}}
# this code works a-ok
for key, value in list.items():
names = []
for key, value in list.items():
names.append(value['name'])
# and these consecutive comprehensions also work...
keys = [value for key, value in list.items()]
names = [each['name'] for each in keys]
but how can the last two be combined?
>>> d = {'1':{'name':'fred'}, '2':{'name':'john'}}
You can use the following modification to your list comprehension
>>> [value.get('name') for key, value in d.items()]
['john', 'fred']
Although in this case, you don't need the key for anything so you can just do
>>> [value.get('name') for value in d.values()]
['john', 'fred']
names = [value['name'] for value in list.values()]
names = [value['name'] for key, value in list.items()]
names = [value['name'] for key, value in list.items()]
Since value is defined in the for part of the comprehension, you can perform operations on value for the item part of the comprehension. As noted above, you can simplify this by using list.values() instead.

Dict comprehension, tuples and lazy evaluation

I am trying to see if I can pull off something quite lazy in Python.
I have a dict comprehension, where the value is a tuple. I want to be able to create the second entry of the tuple by using the first entry of the tuple.
An example should help.
dictA = {'a': 1, 'b': 3, 'c': 42}
{key: (a = someComplexFunction(value), moreComplexFunction(a)) for key, value in dictA.items()}
Is it possible that the moreComplexFunction uses the calculation in the first entry of the tuple?
You could add a second loop over a one-element tuple:
{key: (a, moreComplexFuntion(a)) for key, value in dictA.items()
for a in (someComplexFunction(value),)}
This gives you access to the output of someComplexFunction(value) in the value expression, but that's rather ugly.
Personally, I'd move to a regular loop in such cases:
dictB = {}
for key, value in dictA.items():
a = someComplexFunction(value)
dictB[key] = (a, moreComplexFunction(a))
and be done with it.
or, you could just write a function to return the tuple:
def kv_tuple(a):
tmp = someComplexFunction(a)
return (a, moreComplexFunction(tmp))
{key:kv_tuple(value) for key, value in dictA.items()}
this also gives you the option to use things like namedtuple to get names for the tuple items, etc. I don't know how much faster/slower this would be though... the regular loop is likely to be faster (fewer function calls)...
Alongside Martijn's answer, using a generator expression and a dict comprehension is also quite semantic and lazy:
dictA = { ... } # Your original dict
partially_computed = ((key, someComplexFunction(value))
for key, value in dictA.items())
dictB = {key: (a, moreComplexFunction(a)) for key, a in partially_computed}

How to iterate through dict values containing lists and remove items?

Python novice here. I have a dictionary of lists, like so:
d = {
1: ['foo', 'foo(1)', 'bar', 'bar(1)'],
2: ['foobaz', 'foobaz(1)', 'apple', 'apple(1)'],
3: ['oz', 'oz(1)', 'boo', 'boo(1)']
}
I am trying to figure out how to loop through the keys of the dictionary and the corresponding list values and remove all strings in each in list with a parantheses tail. So far this is what I have:
for key in keys:
for word in d[key]...: # what else needs to go here?
regex = re.compile('\w+\([0-9]\)')
re.sub(regex, '', word) # Should this be a ".pop()" from list instead?
I would like to do this with a list comprehension, but as I said, I can't find much information on looping through dict keys and corresponding dict value of lists. What's the most efficient way of setting this up?
You can re-build the dictionary, letting only elements without parenthesis through:
d = {k:[elem for elem in v if not elem.endswith(')')] for k,v in d.iteritems()}
temp_dict = d
for key, value is temp_dict:
for elem in value:
if temp_dict[key][elem].find(")")!=-1:
d[key].remove[elem]
you can't edit a list while iterating over it, so you create a copy of your list as temp_list and if you find parenthesis tail in it, you delete corresponding element from your original list.
Alternatively, you can do it without rebuilding the dictionary, which may be preferable if it's huge...
for k, v in d.iteritems():
d[k] = filter(lambda x: not x.endswith(')'), v)

Converting Dictionary to List? [duplicate]

This question already has answers here:
How can I convert a dictionary into a list of tuples?
(13 answers)
Closed 3 years ago.
I'm trying to convert a Python dictionary into a Python list, in order to perform some calculations.
#My dictionary
dict = {}
dict['Capital']="London"
dict['Food']="Fish&Chips"
dict['2012']="Olympics"
#lists
temp = []
dictList = []
#My attempt:
for key, value in dict.iteritems():
aKey = key
aValue = value
temp.append(aKey)
temp.append(aValue)
dictList.append(temp)
aKey = ""
aValue = ""
That's my attempt at it... but I can't work out what's wrong?
dict.items()
Does the trick.
Converting from dict to list is made easy in Python. Three examples:
>> d = {'a': 'Arthur', 'b': 'Belling'}
>> d.items()
[('a', 'Arthur'), ('b', 'Belling')]
>> d.keys()
['a', 'b']
>> d.values()
['Arthur', 'Belling']
Your problem is that you have key and value in quotes making them strings, i.e. you're setting aKey to contain the string "key" and not the value of the variable key. Also, you're not clearing out the temp list, so you're adding to it each time, instead of just having two items in it.
To fix your code, try something like:
for key, value in dict.iteritems():
temp = [key,value]
dictlist.append(temp)
You don't need to copy the loop variables key and value into another variable before using them so I dropped them out. Similarly, you don't need to use append to build up a list, you can just specify it between square brackets as shown above. And we could have done dictlist.append([key,value]) if we wanted to be as brief as possible.
Or just use dict.items() as has been suggested.
You should use dict.items().
Here is a one liner solution for your problem:
[(k,v) for k,v in dict.items()]
and result:
[('Food', 'Fish&Chips'), ('2012', 'Olympics'), ('Capital', 'London')]
or you can do
l=[]
[l.extend([k,v]) for k,v in dict.items()]
for:
['Food', 'Fish&Chips', '2012', 'Olympics', 'Capital', 'London']
>>> a = {'foo': 'bar', 'baz': 'quux', 'hello': 'world'}
>>> list(reduce(lambda x, y: x + y, a.items()))
['foo', 'bar', 'baz', 'quux', 'hello', 'world']
To explain: a.items() returns a list of tuples. Adding two tuples together makes one tuple containing all elements. Thus the reduction creates one tuple containing all keys and values and then the list(...) makes a list from that.
Probably you just want this:
dictList = dict.items()
Your approach has two problems. For one you use key and value in quotes, which are strings with the letters "key" and "value", not related to the variables of that names. Also you keep adding elements to the "temporary" list and never get rid of old elements that are already in it from previous iterations. Make sure you have a new and empty temp list in each iteration and use the key and value variables:
for key, value in dict.iteritems():
temp = []
aKey = key
aValue = value
temp.append(aKey)
temp.append(aValue)
dictList.append(temp)
Also note that this could be written shorter without the temporary variables (and in Python 3 with items() instead of iteritems()):
for key, value in dict.items():
dictList.append([key, value])
If you're making a dictionary only to make a list of tuples, as creating dicts like you are may be a pain, you might look into using zip()
Its especialy useful if you've got one heading, and multiple rows. For instance if I assume that you want Olympics stats for countries:
headers = ['Capital', 'Food', 'Year']
countries = [
['London', 'Fish & Chips', '2012'],
['Beijing', 'Noodles', '2008'],
]
for olympics in countries:
print zip(headers, olympics)
gives
[('Capital', 'London'), ('Food', 'Fish & Chips'), ('Year', '2012')]
[('Capital', 'Beijing'), ('Food', 'Noodles'), ('Year', '2008')]
Don't know if thats the end goal, and my be off topic, but it could be something to keep in mind.

Categories