Given a list like:
[['james',100,200,300],['james',200,300,400], ['charles',200,200,100]]
I need to add the components of the two lists that have the same first index like so:
[['james',300,500,700],['charles',200,200,100]]
Thanks for the answers. Just found out I have to do so without importing any modules. Is there a way to do so? I've tried using for-loops but cannot find out what to index for.
data=[['james',100,200,300],['james',200,300,400], ['charles',200,200,100]]
dic={}
for sample in data:
if sample[0] in dic.keys():
dic[sample[0]] = [x+y for x,y in zip(dic[sample[0]],sample[1:])]
else:
dic[sample[0]] = sample[1:]
data= [[x]+y for x,y in dic.items()]
Explanation: The for loop iterates over all elements of the list. Using the 1st element of each list, we check if 'dic' has this name as a key or not. If yes, we add to previous values of the key else create the key with the values 'sample[1:]'.The last step converts dictionary 'dic' to the desired list
dic = {}
for row in a:
if row[0] in dic:
dic[row[0]] = [sum(n) for n in zip(*[dic[row[0]], row[1:]])]
else:
dic[row[0]] = row[1:]
ans = []
for key in dic:
ans.append([key, *dic[key]])
You can create a dictionary with the names as keys and the subsequent numbers as the value.
Finally you can convert the dictionary to a list of lists.
[sum(n) for n in zip(*[dic[row[0]], row[1:]])] is used to sum up the elements of 2 corresponding lists, refer here : https://stackoverflow.com/a/11280563/10077354
Hmm... no imports sounds like homework. Python is all about re-use. However, just for fun:
data = [['james', 100, 200, 300], ['james', 200, 300, 400], ['charles', 200, 200, 100]]
def combine_lists(data, result=None):
if result is None:
result = []
if data:
return combine_lists(data[1:], _add_sublist(data[0], result))
return result
def _add_sublist(sublist, result):
result_out = []
combined = False
for result_sublist in result:
if sublist[0] == result_sublist[0]:
result_out.append([sublist[0], *[from_elt + into_elt
for from_elt, into_elt in zip(sublist[1:], result_sublist[1:])]])
combined = True
else:
result_out.append(result_sublist)
if not combined:
result_out.append(sublist)
return result_out
Running the function in a shell using your data:
In [4]: combine_lists(data)
Out[4]: [['james', 300, 500, 700], ['charles', 200, 200, 100]]
Make sure you understand the code before handing it in :)
you can use collections.defaultdict:
from collections import defaultdict
l = [['james',100,200,300],['james',200,300,400], ['charles',200,200,100]]
d = defaultdict(list)
for k, *v in l:
d[k].append(v)
[[k, *[sum(e) for e in zip(*v)]] for k, v in d.items()]
output:
[['james', 300, 500, 700], ['charles', 200, 200, 100]]
without importing any module:
l = [['james',100,200,300],['james',200,300,400], ['charles',200,200,100]]
d = {}
for k, *v in l:
d.setdefault(k, []).append(v)
[[k, *[sum(e) for e in zip(*v)]] for k, v in d.items()]
output:
l = [['james',100,200,300],['james',200,300,400], ['charles',200,200,100]]
Related
I am trying to convert a list of lists data structure to a dictionary of dictionaries.
The list is defined as follows:
l = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]
My aim is to have the dictionary structure as follows:
#{'PP' : {'Holesovice' : {'Ear-rings' : 2000, 'Skirts' : 1000},
# 'E-shop' : {'Dresses' : 1500}},
# 'BM' : {'Holesovice' : {'Butterfly' : 1600}}
#}
This bit of code does not return desired output:
labels_d = {}
items_d = {}
shops_d = {}
for index, row in enumerate(l):
items_d[row[1]] = row[3]
shops_d[row[2]] = items_d
labels_d[row[0]] = shops_d
print(labels_d)
I found some posts that deal with converting lists to dictionaries here and here but I did not make it work the way I want. Is there any 'clean' way how to achieve the structure posted above?
Using dict.setdefault(key, {}) is a good way to approach the creation of nested dictionaries of fixed depth.
l = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]
d = {}
for tag, item, source, qty in l:
d.setdefault(tag, {}).setdefault(source, {})[item] = qty
Output
{'BM': {'Holesovice': {'Butterfly': 1600}},
'PP': {'E-shop': {'Dresses': 1500},
'Holesovice': {'Ear-rings': 2000, 'Skirts': 1000}}}
Generalization
The above solution can be made more general by building a class of nested dictionary, dropping the requirements to have a fixed depth.
class NestedDict(dict):
def __getitem__(self, item):
if item not in self:
self[item] = NestedDict()
return super().__getitem__(item)
d = NestedDict()
for tag, item, source, qty in l:
d[tag][source][item] = qty
Also notice that the class approach is created so it only creates an object if the key does not exist while the setdefault approach created an empty dict on every access.
You can use the infinitely nested defaultdict trick:
from collections import defaultdict
def nested_dict():
return defaultdict(nested_dict)
nd = nested_dict()
for a, b, c, d in l:
nd[a][c][b] = d
You can use collections.defaultdict and iterate. In this case, you can define precisely a nested dictionary to reflect your data structure.
from collections import defaultdict
L = [['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]]
d = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
for code, item, shop, value in L:
d[code][shop][item] = value
Result
defaultdict({'BM': defaultdict({'Holesovice': defaultdict(int, {'Butterfly': 1600})}),
'PP': defaultdict({'E-shop': defaultdict(int, {'Dresses': 1500}),
'Holesovice': defaultdict(int,
{'Ear-rings': 2000, 'Skirts': 1000})})})
def toNested1(l):
def addKeyDict(map,key):
if key not in map:
item = map[key] = {}
return item
return map[key]
zz = {}
for a0,a1,a2,a3 in l :
addKeyDict( addKeyDict( zz, a0) , a2 )[a1] = a3
return zz
Here post a pretty straightforward way to compose a new dictionary:
If the items in each row of list not in the corresponding depth of dictionary, just add/append the key-value pair to the dict.
code:
list = [
['PP','Ear-rings', 'Holesovice', 2000],
['PP','Skirts', 'Holesovice', 1000],
['PP','Dresses', 'E-shop', 1500],
['BM','Butterfly', 'Holesovice', 1600]
]
dicta = {}
for row in list:
if row[0] not in dicta.keys():
dicta[row[0]] = {row[2]:{row[1]:row[3]}}
continue
if row[2] not in dicta[row[0]].keys():
dicta[row[0]][row[2]] = {row[1]:row[3]}
continue
if row[1] not in dicta[row[0]][row[2]].keys():
dicta[row[0]][row[2]][row[1]] = row[3]
print(dicta)
output:
{'BM': {'Holesovice': {'Butterfly': 1600}},
'PP': {'E-shop': {'Dresses': 1500},
'Holesovice': {'Ear-rings': 2000, 'Skirts': 1000}}}
I have the following Python list:
list1 = ['EW:G:B<<LADHFSSFAFFF', 'CB:E:OWTOWTW', 'PP:E:A,A<F<AF', 'GR:A:OUO-1-XXX-EGD:forthyFive:1:HMJeCXX:7', 'SX:F:-111', 'DS:f:115.5', 'MW:AA:0', 'MA:A:0XT:i:0', 'EY:EE:KJERWEWERKJWE']
I would like to take the entries of this list and create a dictionary of key-values pairs that looks like
dictionary_list1 = {'EW':'G:B<<LADHFSSFAFFF', 'CB':'E:OWTOWTW', 'PP':'E:A,A<F<AF', 'GR':'A:OUO-1-XXX-EGD:forthyFive:1:HMJeCXX:7', 'SX':'F:-111', 'DS':'f:115.5', 'MW':'AA:0', 'MA':'A:0XT:i:0', 'EW':'EE:KJERWEWERKJWE'}
How does one parse/split the list above list1 to do this? My first instinct was to try try1 = list1.split(":"), but then I think it is impossible to retrieve the "key" for this list, as there are multiple colons :
What is the most pythonic way to do this?
You can specify a maximum number of times to split with the second argument to split.
list1 = ['EW:G:B<<LADHFSSFAFFF', 'CB:E:OWTOWTW', 'PP:E:A,A<F<AF', 'GR:A:OUO-1-XXX-EGD:forthyFive:1:HMJeCXX:7', 'SX:F:-111', 'DS:f:115.5', 'MW:AA:0', 'MA:A:0XT:i:0', 'EW:EE:KJERWEWERKJWE']
d = dict(item.split(':', 1) for item in list1)
Result:
>>> import pprint
>>> pprint.pprint(d)
{'CB': 'E:OWTOWTW',
'DS': 'f:115.5',
'EW': 'EE:KJERWEWERKJWE',
'GR': 'A:OUO-1-XXX-EGD:forthyFive:1:HMJeCXX:7',
'MA': 'A:0XT:i:0',
'MW': 'AA:0',
'PP': 'E:A,A<F<AF',
'SX': 'F:-111'}
If you'd like to keep track of values for non-unique keys, like 'EW:G:B<<LADHFSSFAFFF' and 'EW:EE:KJERWEWERKJWE', you could add keys to a collections.defaultdict:
import collections
d = collections.defaultdict(list)
for item in list1:
k,v = item.split(':', 1)
d[k].append(v)
Result:
>>> pprint.pprint(d)
{'CB': ['E:OWTOWTW'],
'DS': ['f:115.5'],
'EW': ['G:B<<LADHFSSFAFFF', 'EE:KJERWEWERKJWE'],
'GR': ['A:OUO-1-XXX-EGD:forthyFive:1:HMJeCXX:7'],
'MA': ['A:0XT:i:0'],
'MW': ['AA:0'],
'PP': ['E:A,A<F<AF'],
'SX': ['F:-111']}
You can also use str.partition
list1 = ['EW:G:B<<LADHFSSFAFFF', 'CB:E:OWTOWTW', 'PP:E:A,A<F<AF', 'GR:A:OUO-1-XXX-EGD:forthyFive:1:HMJeCXX:7', 'SX:F:-111', 'DS:f:115.5', 'MW:AA:0', 'MA:A:0XT:i:0', 'EW:EE:KJERWEWERKJWE']
d = dict([t for t in x.partition(':') if t!=':'] for x in list1)
# or more simply as TigerhawkT3 mentioned in the comment
d = dict(x.partition(':')[::2] for x in list1)
for k, v in d.items():
print('{}: {}'.format(k, v))
Output:
MW: AA:0
CB: E:OWTOWTW
GR: A:OUO-1-XXX-EGD:forthyFive:1:HMJeCXX:7
PP: E:A,A<F<AF
EW: EE:KJERWEWERKJWE
SX: F:-111
DS: f:115.5
MA: A:0XT:i:0
What is an efficient way to convert a list into separate elements in python?
I have a dataset that looks like this;
['StudentA','80','94','93']
['StudentB','93','94']
I would like to reshape the data so that each student/score has its own row;
['StudentA','80']
['StudentA','94']
etc...
You could use a list comprehension, like this:
data = ['StudentA','80','94','93']
res = [[data[0], x] for x in data[1:]]
This sets res to [['StudentA', '80'], ['StudentA', '94'], ['StudentA', '93']].
c=['StudentA','80','94','93']
d=[[c[0], p] for p in c[1:]]
This dict comprehension will group you data by student name:
d = {x[0]: x[1:] for x in dataset}
i.e.:
>>> d
{'StudentA': ['80', '94', '93'], 'StudentB': ['93', '94']}
from which you can extract individual pairs with a nested for loop or list comprehension:
>>> [(k, w) for k, v in d.items() for w in v]
[('StudentA', '80'), ('StudentA', '94'), ('StudentA', '93'), ('StudentB', '93'), ('StudentB', '94')]
If it were a list (all_students) containing each of these lines, you could do what you want, by doing :
result = []
for student in all_students:
student_name = student[0]
result.extend([[student_name, value] for value in student[1:]]
print(result)
Couple student with it's respective data using a dictionary.
def to_dict(l):
d = {}
for i in l:
key = i[0]
value = i[1:]
d[key] = value
return d
Sample output:
l = [['studentA', 90, 90],['studentB', 78, 40]]
print to_dict(l)
>>> {'studentB': [78, 40], 'studentA': [90, 90]}
for key, value in d.iteritems():
for i in value:
print key, i
>>> studentB 78
>>> studentB 40
>>> studentA 90
>>> studentA 90
dic = {('UUU','UUC'):'F',('GUU','GUC','GUA','GUG'):'V'}
L = ['UUU', 'GUG', 'GUU']
As you see each elements of list(L) are in dictionary as keys. Now i want to replace each elements of L by its corresponding values. Output would be:
output = ['F','V']
How can i do that?
One way would be to decompose the keys into individual elements, and create a new dict from those:
new_dic = {}
for k, v in dic.items():
for sub_k in k:
new_dic[sub_k] = v
Now it's a simple matter of looping through the list:
output = [new_dic[i] for i in L]
and you can de-duplicate with set:
output = list(set(output))
Using list compression:
In [1]: dic = {('UUU','UUC'):'F',('GUU','GUC','GUA','GUG'):'V'}
In [2]: L = ['UUU', 'GUG', 'GUU']
In [3]: list(set([v for k,v in dic.items() for x in L if x in k]))
Out [3]: ['V', 'F']
I have two separate Python List that have common key names in their respective dictionary. The second list called recordList has multiple dictionaries with the same key name that I want to append the first list clientList. Here are examples lists:
clientList = [{'client1': ['c1','f1']}, {'client2': ['c2','f2']}]
recordList = [{'client1': {'rec_1':['t1','s1']}}, {'client1': {'rec_2':['t2','s2']}}]
So the end result would be something like this so the records are now in a new list of multiple dictionaries within the clientList.
clientList = [{'client1': [['c1','f1'], [{'rec_1':['t1','s1']},{'rec_2':['t2','s2']}]]}, {'client2': [['c2','f2']]}]
Seems simple enough but I'm struggling to find a way to iterate both of these dictionaries using variables to find where they match.
When you are sure, that the key names are equal in both dictionaries:
clientlist = dict([(k, [clientList[k], recordlist[k]]) for k in clientList])
like here:
>>> a = {1:1,2:2,3:3}
>>> b = {1:11,2:12,3:13}
>>> c = dict([(k,[a[k],b[k]]) for k in a])
>>> c
{1: [1, 11], 2: [2, 12], 3: [3, 13]}
Assuming you want a list of values that correspond to each key in the two lists, try this as a start:
from pprint import pprint
clientList = [{'client1': ['c1','f1']}, {'client2': ['c2','f2']}]
recordList = [{'client1': {'rec_1':['t1','s1']}}, {'client1': {'rec_2':['t2','s2']}}]
clientList.extend(recordList)
outputList = {}
for rec in clientList:
k = rec.keys()[0]
v = rec.values()[0]
if k in outputList:
outputList[k].append(v)
else:
outputList[k] = [v,]
pprint(outputList)
It will produce this:
{'client1': [['c1', 'f1'], {'rec_1': ['t1', 's1']}, {'rec_2': ['t2', 's2']}],
'client2': [['c2', 'f2']]}
This could work but I am not sure I understand the rules of your data structure.
# join all the dicts for better lookup and update
clientDict = {}
for d in clientList:
for k, v in d.items():
clientDict[k] = clientDict.get(k, []) + v
recordDict = {}
for d in recordList:
for k, v in d.items():
recordDict[k] = recordDict.get(k, []) + [v]
for k, v in recordDict.items():
clientDict[k] = [clientDict[k]] + v
# I don't know why you need a list of one-key dicts but here it is
clientList = [dict([(k, v)]) for k, v in clientDict.items()]
With the sample data you provided this gives the result you wanted, hope it helps.