Related
This list:
data=[[{'t1':'text1.txt','date1':'class1'}],[{'t2':'text2.txt','date2':'class2'}]]
data
gives
[[{'t1': 'text1.txt', 'date1': 'class1'}],
[{'t2': 'text2.txt', 'date2': 'class2'}]]
and I want to turn it into this:
EDIT brackets added
[[{'text1.txt': 'class1'}], [{'text2.txt': 'class2'}]]
which means:
to create a list where each sublist inside, will be comprised of a dictionary where the key would be the value of the first dictionary in the first sublist and the value would be the value of the second dictionary of the first sublist and so on for the following sublists.
My attempt was this:
se=[]
for i in data:
for j in i:
jk=j.values()
se.append(jk)
se
Iterate through each dictionary in nested list and create a tuple from values() method for each dictionary like this tuple(dict.values()). After converting to tuple you can use dict() to create dictionary from the tuple like this dict([tuple(dict.values())])
Note: If your dictionary has exactly two keys then only it will work.
res = [[dict([tuple(d.values())]) for d in lst]for lst in data]
print(res)
Output:
[[{'text1.txt': 'class1'}], [{'text2.txt': 'class2'}]]
Your code does most of the job. You can add another line to get the desired results:
In [108]: se
Out[108]: [dict_values(['text1.txt', 'class1']), dict_values(['text2.txt', 'class2'])]
In [109]: [[{list(x)[0]:list(x)[1]} for x in se]]
Out[109]: [[{'text1.txt': 'class1'}, {'text2.txt': 'class2'}]]
Try this:
data=[[{'t1':'text1.txt','date1':'class1'}],[{'t2':'text2.txt','date2':'class2'}]]
all_vals = [];
for i in data:
for j in i:
for key in j:
all_vals.append(j[key])
new_list = [];
for i in range(0,len(all_vals)-1):
if (i % 2) == 0:
new_dict = {};
new_dict = {all_vals[i]:all_vals[i+1]}
new_list.append(new_dict)
else:
continue
print(new_list)
Output:
[{'text1.txt': 'class1'}, {'text2.txt': 'class2'}]
This code works regardless of the length of your list.
The following function should convert the inputs to the outputs you requested.
def convert_to_list_of_list_of_dictionaries(input_dictionaries):
ret_dictionaries = []
for inp in input_dictionaries:
k, v = inp[0].values()
ret_dictionaries.append({k, v})
return ret_dictionaries
However, there are a few things going on with the input/outputs that are little concerning and make the data harder to work with.
On the input side, the data is being wrapped in an extra list that in this context, does not provide any function, and forces you to index the first element of the inner list to access the dict k, v = inp[0].values(). On the output side, we're doing the same thing, which makes it harder to iterate over the outputs. It would look something like:
# psuedocode
for kv in reformatted_outputs:
unwrapped_dict = kv[0]
key, value = next(iter(unwrapped_dict.items()))
# process key and value
instead, if you had an output format like ``{'text1.txt': 'class1', 'text2.txt': 'class2'}`, you could process data like:
key, value in reformatted_outputs.items():
# process key and value
If you have the ability to modify the inputs and outputs of what you're working on, this could save you some trouble, and anyone you're working with some head scratches.
If you wanted to modify the output format, your function could look something like:
def convert_to_single_dictionary(input_dictionaries):
ret = {}
for inp in input_dictionaries:
print(inp)
# it looks like the input data is being wrapped in an extra list
k, v = inp[0].values()
ret[k] = v
return ret
Hope this is helpful and thanks for asking the question!
I am accessing a list of dictionary items list_of_dict = [{'ka':'1a', 'kb':'1b', 'kc':'1c'},{'ka':'2a'},{'ka':'3a', 'kb':'3b', 'kc':'3c'}], and trying to conditionally append each entry to another list article_list using a function add_entries.
My desired output
article_list = [{x:1a, y:1b, z:1c}, {x:2a}, {x:3a, y:3b, z:3c}]
My code:
def add_entries(list_of_dict):
keys = ['x','y','z']
#defining a temporary dictionary here
my_dict = dict.fromkeys(keys,0)
entry_keys = ['ka','kb','kc']
my_list = []
for item in list_of_dict:
# conditionally append the entries into the temporary dictionary maintaining desired key names
my_dict.update({a: item[b] for a,b in zip(keys, entry_keys) if b in item})
my_list.append(my_dict)
return my_list
if __name__ == "__main__":
list_of_dict = [{'ka':'1a', 'kb':'1b', 'kc':'1c'},{'ka':'2a'},{'ka':'3a', 'kb':'3b', 'kc':'3c'}]
article_list = []
returned_list = add_entries(list_of_dict)
article_list.extend(returned_list)
My output
article_list = [{x:3a, y:3b, z:3c}, {x:3a, y:3b, z:3c}, {x:3a, y:3b, z:3c}]
Whats wrong
my_list.append(my_dict) appends a reference to the my_dict object to my_list. Therefore, at the end of the for loop in your example, my_list is a list of references to the exact same dictionary in memory.
You can see this for yourself using the function id. id, at least in CPython, basically gives you the memory address of an object. If you do
article_list.extend(returned_list)
print([id(d) for d in article_list])
You'll get a list of identical memory addresses. On my machine I get
[139920570625792, 139920570625792, 139920570625792]
The consequence is that updating the dictionary affects 'all of the dictionaries' in your list. (quotes because really there are not multiple dictionaries in your list, just many times the exact same one). So in the end, only the last update operation is visible to you.
A good discussion on references and objects in Python can be found in this answer https://stackoverflow.com/a/30340596/8791491
The fix
Moving the definition of my_dict inside the for loop, means that you get a new, separate dictionary for each element of my_list. Now, the update operation won't affect the other dictionaries in the list, and my_list is a list of references to several different dictionaries.
def add_entries(list_of_dict):
keys = ['x','y','z']
entry_keys = ['ka','kb','kc']
my_list = []
for item in list_of_dict:
#defining a new dictionary here
my_dict = dict.fromkeys(keys,0)
# conditionally append the entries into the temporary dictionary maintaining desired key names
my_dict.update({a: item[b] for a,b in zip(keys, entry_keys) if b in item})
my_list.append(my_dict)
return my_list
You can use this.
keys=['x','y','z']
res=[{k1:d[k]} for d in list_of_dict for k,k1 in zip(d,keys)]
output
[{'x': '1a'},
{'y': '1b'},
{'z': '1c'},
{'x': '2a'},
{'x': '3a'},
{'y': '3b'},
{'z': '3c'}]
Try this:
list_new_d=[]
for d in list_of_dict:
new_d={}
for k,v in d.items():
if k == 'ka':
new_d['x'] = v
if k == 'kb':
new_d['y'] = v
if k == 'kc':
new_d['z'] = v
list_new_d.append(new_d)
I am looking to learn how to pass certain keys/values in a dictionary to another function within a for loop. The "certain" keys all share the same initial string and are incremented by a trailing integer like this:
data = {}
data["HMD1"] = [a,b,c]
data["HMD2"] = [d,f,g] #and so on...
There are other keys with dissimilar names witin the same dictionary. Now within a for loop I would like to pass the values for each key that starts with "HMD" to another function. Here is a minimal working example of a failed attempt:
data = {}
data["HMD1"] = [0,2,3]
data["HMD2"] = [5,6,4]
data["not"] = 1237659398
data["HMD3"] = [1,1,1]
def dummyfun(vargin):
print(vargin)
return vargin
for f in range(1,2,1):
out = dummyfun(data[eval(''.join(("HMD",str(f))))])
This was a poor guess, of course it returns an error because eval() tries to evaluate "HMD1" which is not a variable but a key in data. Does anyone know how to do this properly?
You don't need eval at all for this. You only need to build the string with .format for example
for f in range(1,4): #range don't include the end point
out = dummyfun(data["HMD{}".format(f)])
with this you get the desire result. But that will fail if the key is not in the dict, you can check it first, catch the exception or provide a default value in case the desire key is not there
#check first
for f in range(1,4):
key = "HMD{}".format(f)
if key in data:
out = dummyfun(data[key])
#catch the exception
for f in range(1,4):
try:
out = dummyfun(data["HMD{}".format(f)])
except KeyError:
print("key",f,"is not in the data")
#provide a default value
for f in range(1,4):
out = dummyfun(data.get("HMD{}".format(f),None))
Just iterate through the dictionary using a for loop and use an if statement to check for validity of the keys:
for key in yourDict: #a for loop for dict iterates through its keys
if 'HMD' in key: #or you can replace with any other conditional
#DO WHAT YOU WANT TO DO HERE
And here's a quick working example:
>>> data = {'HMD1': [1,2,3], 'HMD23':'heyo mayo', 'HMNOT2':'if this prints, I did something wrong'}
>>> for key in data:
... if 'HMD' in key:
... print data[key]
...
[1, 2, 3]
heyo mayo
With further understand of what you want, you can also look at this backwards and create key strings and print the values that those key's point to:
#let's say you want to print HMD1, HMD2, HMD4, but not anything else
keylist = [#list of keys that you want]
for key in keylist:
if key in data:
print data[key]
and, again, a working example.
>>> data = {'HMD1': [1,2,3], 'HMD3':'heyo mayo, this shouldnt print', 'HMD4':123, 'HMD2':['g', 'h', 'i'], 'HMNOT2':'if this prints, I did something wrong'}
>>> keylist = ['HMD1', 'HMD2', 'HMD4']
>>> for key in keylist:
... if key in data:
... print data[key]
...
[1, 2, 3]
['g', 'h', 'i']
123
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()
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.