Related
Input:
data = [
{'name': 'A', 'value': 19, 'no': 1},
{'name': 'B', 'value': 5, 'no': 2},
{'name': 'A', 'value': 19, 'no': 3}
]
request_change_data = [
{'name': 'A', 'value': 35, 'no': 1},
{'name': 'B', 'value': 10, 'no': 2},
{'name': 'A', 'value': 40, 'no': 3}
]
expected_result:
data = [
{'name': 'A', 'value': 35, 'no': 1},
{'name': 'B', 'value': 10, 'no': 2},
{'name': 'A', 'value': 40, 'no': 3}
]
But actual:
[
{'name': 'A', 'value': 40, 'no': 1},
{'name': 'B', 'value': 10, 'no': 2},
{'name': 'A', 'value': 40, 'no': 3}
]
My code is:
data = [{'name': 'A', 'value': 19, 'no': 1}, {'name': 'B', 'value': 5, 'no': 2}, {'name': 'A', 'value': 19, 'no': 3}]
requests = [{'name': 'A', 'value': 35, 'no': 1}, {'name': 'B', 'value': 10, 'no': 2}, {'name': 'A', 'value': 40, 'no': 3}]
def test(data, requests):
for k, v in enumerate(data):
for request in requests:
if v['name'] == request['name']:
v['value'] =request['value']
return data
print(test(data, requests))
How could I change the duplicate stt1 vĂ stt3. I used for to update the value of the key, it always updates only stt3 value is 40.
Please help. Thanks in advance
Each time you iterate through data, you then iterate over all of the request dictionaries, and your code only checks the name fields for each dictionary and then updates the value field in the dict from data if they match.
However, you have multiple dictionaries in requests with the same name, so if you were working the first data dict:
{'name': 'A', 'value': 19, 'no': 1}
You'd get this in for request in requests:
Iteration 1: request = {'name': 'A', 'value': 35, 'no': 1},
Iteration 2: request = {'name': 'B', 'value': 10, 'no': 2},
Iteration 3: request = {'name': 'A', 'value': 40, 'no': 3}
So you'd end up updating the data dict twice, first with v['value'] = 35 and then with v['value'] = 40.
So for your data, you want to check both name and no in the dicts and if they both match, then update the fields. Here's a fixed version of your code that does that:
data = [{'name': 'A', 'value': 19, 'no': 1}, {'name': 'B', 'value': 5, 'no': 2}, {'name': 'A', 'value': 19, 'no': 3}]
requests = [{'name': 'A', 'value': 35, 'no': 1}, {'name': 'B', 'value': 10, 'no': 2}, {'name': 'A', 'value': 40, 'no': 3}]
# You didn't seem to need the idx from enumerating so I removed it
# You also don't need to return data because lists/dicts are mutable
# types so you're modifying the actual dicts you pass in
def test(data, requests):
for d in data:
for request in requests:
if d['name'] == request['name'] and d['no'] == request['no']:
d['value'] = request['value']
test(data, requests)
print(data)
And I get this output, which is your expected:
[
{'name': 'A', 'value': 35, 'no': 1},
{'name': 'B', 'value': 10, 'no': 2},
{'name': 'A', 'value': 40, 'no': 3}
]
I have this one list
list_dict = [
{'id': 1},
{'item': 'apple'},
{'id': 2},
{'item': 'pear'},
{'id': 1},
{'item': 'peach'},
{'id': 2},
{'item': 'kiwi'},
{'id': 3},
{'item': 'banana'},
{'id': 4},
{'item': 'mango'},
{'id': 1},
{'item': 'watermelon'},
{'id': 2},
{'item': 'plum'},
{'id': 3},
{'item': 'grapes'}]
and I want to split like this (start to make sublist when "id" is 1)
result = [
[{'id': 1},
{'item': 'apple'},
{'id': 2},
{'item': 'pear'}],
[{'id': 1},
{'item': 'peach'},
{'id': 2},
{'item': 'kiwi'},
{'id': 3},
{'item': 'banana'},
{'id': 4},
{'item': 'mango'}],
[{'id': 1},
{'item': 'watermelon'},
{'id': 2},
{'item': 'plum'},
{'id': 3},
{'item': 'grapes'}]]
Some nested for loop will work
list_dict = [{"id":1},{"item":"apple"},{"id":2},{"item":"pear"},{"id":1},{"item":"peach"},{"id":2},{"item":"kiwi"},{"id":3},{"item":"banana"},{"id":4},{"item":"mango"},{"id":1},{"item":"watermelon"},{"id":2},{"item":"plum"},{"id":3},{"item":"grapes"}]
output = []
temp = []
for i in list_dict:
if i.get('id', -1) == 1 and temp:
output.append(temp.copy())
temp.clear()
temp.append(i)
else:
temp.append(i)
output.append(temp.copy())
print(output)
#[[{'id': 1}, {'item': 'apple'}, {'id': 2}, {'item': 'pear'}], [{'id': 1}, {'item': 'peach'}, {'id': 2}, {'item': 'kiwi'}, {'id': 3}, {'item': 'banana'}, {'id': 4}, {'item': 'mango'}], [{'id': 1}, {'item': 'watermelon'}, {'id': 2}, {'item': 'plum'}, {'id': 3}, {'item': 'grapes'}]]
Maybe something like this?
main_list = []
current_list = []
for el in list_dict:
if el.get("id", 0) == 1:
if current_list:
main_list.append(current_list)
current_list = [el]
else:
current_list.append(el)
if current_list:
main_list.append(current_list)
print(main_list)
I have list:
my_list = [{'date': '10.06.2016',
'account': [{'name': 'a'},
{'name': 'a'},
{'name': 'b'},
{'name': 'b'}]},
{'date': '22.06.2016',
'account': [{'name': 'a'},
{'name': 'a'}]}]
I want to remove duplicates from the list of dictionaries in 'account':
my_list = [{'date': '10.06.2016',
'account': [{'name': 'a'},
{'name': 'b'}]},
{'date': '22.06.2016',
'account': [{'name': 'a'}]}]
When using set, I get the following error:
TypeError: unhashable type: 'dict'
Can anybody help me with this problem?
This structure is probably over complicated, but it gets the job done.
my_list = [{'date': '10.06.2016',
'account': [{'name': 'a'},
{'name': 'a'},
{'name': 'b'},
{'name': 'b'}]},
{'date': '22.06.2016',
'account': [{'name': 'a'},
{'name': 'a'}]}]
>>> [{'date': date,
'account': [{'name': name} for name in group]
} for group, date in zip([set(account.get('name')
for account in item.get('account'))
for item in my_list],
[d.get('date') for d in my_list])]
[{'account': [{'name': 'a'}, {'name': 'b'}], 'date': '10.06.2016'},
{'account': [{'name': 'a'}], 'date': '22.06.2016'}]
def deduplicate_account_names(l):
for d in l:
names = set(map(lambda d: d.get('name'), d['account']))
d['account'] = [{'name': name} for name in names]
# even shorter:
# def deduplicate_account_names(l):
# for d in l:
# d['account'] = [{'name': name} for name in set(map(lambda d: d.get('name'), d['account']))]
my_list = [{'date': '10.06.2016',
'account': [{'name': 'a'},
{'name': 'a'},
{'name': 'b'},
{'name': 'b'}]},
{'date': '22.06.2016',
'account': [{'name': 'a'},
{'name': 'a'}]}]
deduplicate_account_names(my_list)
print(my_list)
# [ {'date': '10.06.2016',
# 'account': [ {'name': 'a'},
# {'name': 'b'} ] },
# {'date': '22.06.2016',
# 'account': [ {'name': 'a'} ] } ]
Sets can only have hashable members and neither lists nor dicts are - but they can be checked for equality.
you can do
def without_duplicates(inlist):
outlist=[]
for e in inlist:
if e not in outlist:
outlist.append(e)
return outlist
this can be slow for really big lists
Give this code a try:
for d in my_list:
for k in d:
if k == 'account':
v = []
for d2 in d[k]:
if d2 not in v:
v.append(d2)
d[k] = v
This is what you get after running the snippet above:
In [347]: my_list
Out[347]:
[{'account': [{'name': 'a'}, {'name': 'b'}], 'date': '10.06.2016'},
{'account': [{'name': 'a'}], 'date': '22.06.2016'}]
how can I get the max and min value from code like this:
[{'sum': 44, 'code': 'A'},
{'sum': 1, 'code': 'B'},
{'sum': 44, 'code': 'B'},
{'sum': 33, 'code': 'B'},
{'sum': 2, 'code': 'C'},
{'sum': 694, 'code': 'A'},
{'sum': 12, 'code': 'B'},
{'sum': 5, 'code': 'C'}]
And i need results like this:
#max
[{'sum': 694, 'code': 'A'},
{'sum': 44, 'code': 'B'},
{'sum': 5, 'code': 'C'}]
#min
[{'sum': 44, 'code': 'A'},
{'sum': 1, 'code': 'B'},
{'sum': 2, 'code': 'C'}]
You can use itertools.groupby cf. How do I use Python's itertools.groupby()? for details, and max's key argument. This makes for a short code:
from itertools import groupby
input = [
{'sum': 44, 'code': 'A'},
{'sum': 1, 'code': 'B'},
{'sum': 44, 'code': 'B'},
{'sum': 33, 'code': 'B'},
{'sum': 2, 'code': 'C'},
{'sum': 694, 'code': 'A'},
{'sum': 12, 'code': 'B'},
{'sum': 5, 'code': 'C'}
]
# groupby requires its input to be sorted by group key
input.sort(key=lambda x: (x['code'], x['sum'])
maximums = list()
minimums = list()
for code, group in groupby(input, key=lambda x: x['code']):
group = list(group) # Consume iterator
maximums.append(group[-1])
minimums.append(group[0])
print 'max:', maximums
print 'min:', minimums
This will get you:
max: [{'sum': 694, 'code': 'A'}, {'sum': 44, 'code': 'B'}, {'sum': 5, 'code': 'C'}]
min: [{'sum': 44, 'code': 'A'}, {'sum': 1, 'code': 'B'}, {'sum': 2, 'code': 'C'}]
from operator import itemgetter
from itertools import groupby
sorted1 = sorted(my_list,key=itemgetter("code","sum"))
#the line above is where the magic happens it sorts the list first on code and then on sum, this leads it to be grouped by code and within each group the results are sorted
maxes = []
mins = []
for code,results in groupby(sorted1,itemgetter("code"))
results = list(results)
maxes.append(results[-1])
mins.append(results[0])
you could use a custom comparison key:
max(my_list, key=lambda my_dict: my_dict.keys()[0])
You can set up dictionaries to hold the max and min values. Then loop through each dictionary item in your list and compare against the max and min values and update if required. Also, insert new codes into the max/min dictionaries.
max_ = {}
min_ = {}
for item in lst:
code, val = item['code'], item['sum']
if code not in max_ or val > max_[code]:
max_[code] = val
if code not in min_ or val < min_[code]:
min_[code] = val
>>> max_
{'A': 694, 'B': 44, 'C': 5}
>>>min_
{'A': 44, 'B': 1, 'C': 2}
If you need your specified format, this can be easily recovered as follows:
[{'code': code, 'sum': val} for code, val in max_.iteritems()]
# Max
[{'code': 'A', 'sum': 694}, {'code': 'C', 'sum': 5}, {'code': 'B', 'sum': 44}]
def get_max(lst):
dict = {}
for el in lst:
code = el['code']
sum = el['sum']
if code in dict:
if dict[code] < sum:
dict[code] = sum
else:
dict[code] = sum
return dict
def get_min(lst):
dict = {}
for el in lst:
code = el['code']
sum = el['sum']
if code in dict:
if dict[code] > sum:
dict[code] = sum
else:
dict[code] = sum
return dict
this will get you:
{'A': 694, 'C': 5, 'B': 44}
{'A': 44, 'C': 2, 'B': 1}
Mandatory one-liner:
[max((v for v in vals if v['code'] == x), key=lambda y:y['sum']) for x in set(v['code'] for v in vals)]
>>> [{'sum': 694, 'code': 'A'}, {'sum': 5, 'code': 'C'}, {'sum': 44, 'code': 'B'}]
Details:
set(v['code'] for v in vals) gets the unique codes
v for v in vals if v['code'] == x filters the values based on code == x
max(..., key=lambda y:y['sum']) give you the max value of that based on the sum field
Now, creating the set of codes, and then re-filtering based on that is not very efficient, the group_by method is cleaner.
I Have a list as following and I want to convert that as output shown below using List comprehensions. Any help is appreciated.
a = [{'type': 'abc', 'values': 1},
{'type': 'abc', 'values': 2},
{'type': 'abc', 'values': 3},
{'type': 'xyz', 'values': 4},
{'type': 'xyz', 'values': 5},
{'type': 'pqr', 'values': 6},
{'type': 'pqr', 'values': 8},
{'type': 'abc', 'values': 9},
{'type': 'mno', 'values': 10},
{'type': 'def', 'values': 11}]
This is the output I am expecting.
output = {'abc': [1,2,3,9], 'xyz': [4,5], 'pqr': [6,8], 'mno': [10], 'def': [11]}
from operator import itemgetter
from itertools import groupby
a = [{'type': 'abc', 'values': 1},
{'type': 'abc', 'values': 2},
{'type': 'abc', 'values': 3},
{'type': 'xyz', 'values': 4},
{'type': 'xyz', 'values': 5},
{'type': 'pqr', 'values': 6},
{'type': 'pqr', 'values': 8},
{'type': 'abc', 'values': 9},
{'type': 'mno', 'values': 10},
{'type': 'def', 'values': 11}]
typegetter = itemgetter('type')
valuesgetter = itemgetter('values')
groups = groupby(sorted(a, key=typegetter), key=typegetter)
print {k:list(map(valuesgetter, v)) for k, v in groups}
a = [{'type': 'abc', 'values': 1},
{'type': 'abc', 'values': 2},
{'type': 'abc', 'values': 3},
{'type': 'xyz', 'values': 4},
{'type': 'xyz', 'values': 5},
{'type': 'pqr', 'values': 6},
{'type': 'pqr', 'values': 8},
{'type': 'abc', 'values': 9},
{'type': 'mno', 'values': 10},
{'type': 'def', 'values': 11}]
output = {}
for item in a:
output[item['type']] = [item['values']] if output.get(item['type'], None) is None else output[item['type']] + [item['values']]
print output