In python i am getting a list in a variable like :
[ {'store_id': '321', 'first_name': 'A', 'name': 'A'},
{'second_id': '322', 'first_name': 'B', 'name': 'B', },
{'second_id': '323', 'second_name': 'c', 'name': 'c', },
{'second_id': '324', 'second_name': 'A', 'name': 'A', },
]
what i actually want is i want a list without duplicating the name . if it occur once then i want to remove t and create a new list with distinct data.i am stuck here i want all data in new list. how can i remove the duplicate data from the list .
in my case i want a ne list like :
Either
{'second_id': '322', 'first_name': 'B', 'name': 'B', },
{'second_id': '323', 'second_name': 'c', 'name': 'c', },
{'second_id': '324', 'second_name': 'A', 'name': 'A', },
]
Or
[ {'store_id': '321', 'first_name': 'A', 'name': 'A'},
{'second_id': '322', 'first_name': 'B', 'name': 'B', },
{'second_id': '323', 'second_name': 'c', 'name': 'c', },
]
And the code after that i am getting this is given below:
result = {}
data = request.POST
teamName = []
First = Test.objects.filter(d=data.get('id')).values(
'first_id','first_name').annotate(id=F('first_id'),name=F('first_name')).distinct()
Second = Test.objects.filter(id=data.get('id')).values(
'second_id','second_name').annotate(id=F('second_id'),name=F('second_name')).distinct()
combined_results = list(chain(First, Second))
for team in combined_results:
team['text'] = team['name']
team['id'] = team['id']
teamName.append(team)
if not combined_results:
result['status'] = False
result['data'] = ['Data not found']
else:
result['status'] = True
result['data'] = teamName
return JsonResponse(result)
This should give you the second form
names = set()
newList = []
for d in mylist:
if d['name'] in names:
continue
else:
newList.append(d)
names.add(d['name'])
print(newList)
Output:
[{'store_id': '321', 'first_name': 'A', 'name': 'A'},
{'second_id': '322', 'first_name': 'B', 'name': 'B'},
{'second_id': '323', 'second_name': 'c', 'name': 'c'}]
EDIT:
If you want the first form, you will have to sort your original list in descending order of store_id/second_id using:
mylist = sorted(mylist, key=lambda x: x.get('store_id') or x.get('second_id'), reverse=True)
and then filter the list as earlier.
using list comprehension:
lst = [ {'store_id': '321', 'first_name': 'A', 'name': 'A'},
{'second_id': '322', 'first_name': 'B', 'name': 'B', },
{'second_id': '323', 'second_name': 'c', 'name': 'c', },
{'second_id': '324', 'second_name': 'A', 'name': 'A', },
]
uniqueLst = []
lst2 = []
[[lst2.append(x), uniqueLst.append(x['name'])] for x in lst if x['name'] not in uniqueLst]
print(lst2)
I have tried to solve your issue, It may not be the best approach but it does the job.
lets suppose you have this list
orignal_list = [
{'store_id': '321', 'first_name': 'A', 'name': 'A'},
{'second_id': '322', 'first_name': 'B', 'name': 'B', },
{'second_id': '323', 'second_name': 'c', 'name': 'c', },
{'second_id': '324', 'second_name': 'A', 'name': 'A', },
]
so we can make a function which can take original list and return a filtered list.
def filter_list(original_list):
# temp list which will contains the filtered records
temp_list = list()
# loop over original_list
for original_item in original_list:
# get values of dict expect id because every element have different id
original_values = [*original_item.values()][1:]
flag = True
# loop over temp_list
for temp_items in temp_list:
# get values expect the id
temp_values = [*temp_items.values()][1:]
# check if sample/record/item already exists
if original_values == temp_values:
flag = False
if flag:
temp_list.append(original_item)
return temp_list
I hope this will solve your problem I have tried to explain the code using comments,
let me know if you did not understand any thing.
I did something similar with sets. Since A is a set of elements:
for i in A:
if i not in B:
B.append(i)
Related
Hello I have the following list :
Info_Types = [
{'name': 'A'},
{'name': 'B'},
{'name': 'C'}
]
Next, I would like to use this list with a loop in this type of dictionary:
{
"name": Info_Types[i]['name'],
"domainId": "c50d7ff8-0e6d-4132-a528-f286781f017b",
"typeId": "1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1",
"statusId": "00000000-0000-0000-0000-000000005008",
"excludedFromAutoHyperlinking": 'true'
}
The result I want to get is the following:
[{'name': 'A',
'domainId': 'c50d7ff8-0e6d-4132-a528-f286781f017b',
'typeId': '1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1',
'statusId': '00000000-0000-0000-0000-000000005008',
'excludedFromAutoHyperlinking': 'true'},
{'name': 'B',
'domainId': 'c50d7ff8-0e6d-4132-a528-f286781f017b',
'typeId': '1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1',
'statusId': '00000000-0000-0000-0000-000000005008',
'excludedFromAutoHyperlinking': 'true'},
{'name': 'C',
'domainId': 'c50d7ff8-0e6d-4132-a528-f286781f017b',
'typeId': '1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1',
'statusId': '00000000-0000-0000-0000-000000005008',
'excludedFromAutoHyperlinking': 'true'}]
My idea is that I need to use a for loop but I don't really know how to build it. Someone can help me? thanks
It's better to use list comprehension:
result = [
{
"name": name,
"domainId": "c50d7ff8-0e6d-4132-a528-f286781f017b",
"typeId": "1bf1b4ac-f52f-4ff9-be43-f96d76dff4c1",
"statusId": "00000000-0000-0000-0000-000000005008",
"excludedFromAutoHyperlinking": 'true'
}
for name in Info_Types
]
My question is somewhat different from this one.
I have a list of dictionaries as following:
[{'Name': 'A', 'amt1':101, 'amt2':102, 'amt3':103},
{'Name': 'B', 'amt1':201, 'amt2':202, 'amt3':203},
{'Name': 'A', 'amt1':301, 'amt2':302, 'amt3':303},
{'Name': 'C', 'amt1':401, 'amt2':402, 'amt3':403},
{'Name': 'C', 'amt1':501, 'amt2':502, 'amt3':503},
{'Name': 'A', 'amt1':601, 'amt2':602, 'amt3':603}]
I want to sum amt for each name and get following result in list of dict:
[{'Name':'A', 'amt1':1003, 'amt2':1006, 'amt3':1009},
{'Name':'B', 'amt1':201, 'amt2':202, 'amt3':203},
{'Name':'C', 'amt1':902, 'amt2':904, 'amt3':906}]
To extend the linked answer to multiple keys:
def sum_dicts(lst_of_dicts):
out = {}
for d in lst_of_dicts:
for k in d.keys() - {"Name"}:
out.setdefault(d["Name"], {"Name": d["Name"]}).setdefault(k, 0)
out[d["Name"]][k] += d[k]
return list(out.values())
print(sum_dicts(lst))
Prints:
[
{'Name': 'A', 'amt2': 1006, 'amt1': 1003, 'amt3': 1009},
{'Name': 'B', 'amt2': 202, 'amt1': 201, 'amt3': 203},
{'Name': 'C', 'amt2': 904, 'amt1': 902, 'amt3': 906}
]
You can achieve this in the following way:
initial_list = [{'Name': 'A', 'amt1':101, 'amt2':102, 'amt3':103},
{'Name': 'B', 'amt1':201, 'amt2':202, 'amt3':203},
{'Name': 'A', 'amt1':301, 'amt2':302, 'amt3':303},
{'Name': 'C', 'amt1':401, 'amt2':402, 'amt3':403},
{'Name': 'C', 'amt1':501, 'amt2':502, 'amt3':503},
{'Name': 'A', 'amt1':601, 'amt2':602, 'amt3':603}]
temp_dict = {}
final_list = []
i = 0
for item in initial_list:
if item['Name'] not in temp_dict.keys():
final_list.append(item)
temp_dict[item['Name']] = i
i += 1
else:
present_item = final_list[temp_dict[item['Name']]]
for key, value in item.items():
if key != "Name":
present_item[key] += item[key]
print(final_list)
[{'Name': 'A', 'amt1': 1003, 'amt2': 1006, 'amt3': 1009},
{'Name': 'B', 'amt1': 201, 'amt2': 202, 'amt3': 203},
{'Name': 'C', 'amt1': 902, 'amt2': 904, 'amt3': 906}]
We can do it in one expression, but we'll need python3.9+ :(
import json
data = [
{'Name': 'A', 'amt1':101, 'amt2':102, 'amt3':103},
{'Name': 'B', 'amt1':201, 'amt2':202, 'amt3':203},
{'Name': 'A', 'amt1':301, 'amt2':302, 'amt3':303},
{'Name': 'C', 'amt1':401, 'amt2':402, 'amt3':403},
{'Name': 'C', 'amt1':501, 'amt2':502, 'amt3':503},
{'Name': 'A', 'amt1':601, 'amt2':602, 'amt3':603}
]
result = [
{'Name': name} | {
key: sum(
# sum the [key] value
# for all dictionaries with this name
d[key] for d in data if d['Name'] == name
)
for key in ('amt1', 'amt2', 'amt3')
}
# for all unique names
for name in set(d['Name'] for d in data)
]
print(json.dumps(
result, indent=2, sort_keys=True,
))
This is the way, friends.
[
{
"Name": "C",
"amt1": 902,
"amt2": 904,
"amt3": 906
},
{
"Name": "A",
"amt1": 1003,
"amt2": 1006,
"amt3": 1009
},
{
"Name": "B",
"amt1": 201,
"amt2": 202,
"amt3": 203
}
]
I am unsure how you want the data returned but this is how you get the sum of rows
dict = [{'Name': 'A', 'amt1':101, 'amt2':102, 'amt3':103},
{'Name': 'B', 'amt1':201, 'amt2':202, 'amt3':203},
{'Name': 'A', 'amt1':301, 'amt2':302, 'amt3':303},
{'Name': 'C', 'amt1':401, 'amt2':402, 'amt3':403},
{'Name': 'C', 'amt1':501, 'amt2':502, 'amt3':503},
{'Name': 'A', 'amt1':601, 'amt2':602, 'amt3':603}]
for item in dict:
Sum = item['amt1'] + item['amt2'] + item['amt3']
print(item['Name'], Sum)
Attempting to return a specific value of a key that's in a list within a dict. I've tried iterating over items, searching specific ID's and not quite getting the result I'm after.
{
'activeAccount': True,
'country': 'USA',
'state': 'CA',
'users': [
{
'id': 'A',
'firstName': 'Tom',
'lastName': 'Cruise',
'creditScore': '713',
'balance': '65897.22',
'debts': '12414.12',
'savings': '15231.23'
},
{
'id': 'B',
'firstName': 'Jon',
'lastName': 'Snow',
'creditScore': '648',
'balance': '12366.23',
'debts': '522',
'savings': '121588'
},
{
'id': 'C',
'firstName': 'Rick',
'lastName': 'Sanchez',
'creditScore': '655',
'balance': '556425.33',
'debts': '0',
'savings': '125122.23'
},
{
'id': 'D',
'firstName': 'Monty',
'lastName': 'Python',
'creditScore': '815',
'balance': '4512699.13',
'debts': '4.25',
'savings': '5499865.12'
}
]
}
How would I retrieve a specific value of, for example, the credit score of users[2] to return the value?
655
I've tried the solution of cScore = (dict['users'][2]['creditScore']), but this isn't ideal in situations of the objects changing order, etc.
You have to iterate through the list of dicts, looking for one with an id of 2. Then you return the credit score from that dict. Use this starter code:
for account in data_base:
if account['id'] == 2:
score = account['creditScore']
break
Your underlying problem is that you chose a data representation that doesn't match your data access needs. If you always reference your accounts by id, then change your list to a dict, keyed by that value. If you look up accounts through various means, then you need to investigate some data base format that suits your use cases.
The dictionary value of 'users' is a list. So you have to iterate through the list and search for the specific id.
Here's how you can do it.
for i in cust['users']:
if i['id'] == '2':
print (i['creditScore'])
I searched for 'id' == 'D'. The output was 815
The dictionary is defined as :
cust = {
'activeAccount': True,
'country': 'USA',
'state': 'CA',
'users': [
{
'id': 'A',
'firstName': 'Tom',
'lastName': 'Cruise',
'creditScore': '713',
'balance': '65897.22',
'debts': '12414.12',
'savings': '15231.23'
},
{
'id': 'B',
'firstName': 'Jon',
'lastName': 'Snow',
'creditScore': '648',
'balance': '12366.23',
'debts': '522',
'savings': '121588'
},
{
'id': 'C',
'firstName': 'Rick',
'lastName': 'Sanchez',
'creditScore': '655',
'balance': '556425.33',
'debts': '0',
'savings': '125122.23'
},
{
'id': 'D',
'firstName': 'Monty',
'lastName': 'Python',
'creditScore': '815',
'balance': '4512699.13',
'debts': '4.25',
'savings': '5499865.12'
}
]
}
If you need to find the user by ID within of a list of users you can use a filter function:
dict = {
'activeAccount': True,
'country': 'USA',
'state': 'CA',
'users': [
{
'id': 'A',
'firstName': 'Tom',
'lastName': 'Cruise',
'creditScore': '713',
'balance': '65897.22',
'debts': '12414.12',
'savings': '15231.23'
},
{
'id': 'B',
'firstName': 'Jon',
'lastName': 'Snow',
'creditScore': '648',
'balance': '12366.23',
'debts': '522',
'savings': '121588'
},
{
'id': 'C',
'firstName': 'Rick',
'lastName': 'Sanchez',
'creditScore': '655',
'balance': '556425.33',
'debts': '0',
'savings': '125122.23'
},
{
'id': 'D',
'firstName': 'Monty',
'lastName': 'Python',
'creditScore': '815',
'balance': '4512699.13',
'debts': '4.25',
'savings': '5499865.12'
}
]
}
# get the user with ID:"D"
user = list(filter(lambda u: u["id"] == "D", dict["users"]))[0]
# get the value
cScore = user["creditScore"] # <-- Output: 815
Description
lambda u: u["id"] == "D" means: return True if the property "id" of a given element is "D".
It could be rewritten as a plain function:
def check_D(user):
return user["id"] == "D"
user = list(filter(check_D, dict["users"]))[0]
filter( <condition> , dict["users"]) means: to iterate through the list dict["users"] and to return all elements that meet the condition (the "lambda" in this case, or it could be any function that return True or False).
user = list( ... )[0] since a filter function returns an object, it's need to convert the object into a list and to get a first element of the list.
Another option
You can built a list comprehension with a condition (id == "D") and take a first element of the list:
creditScore = [usr["creditScore"] for usr in dict["users"] if usr["id"] == "D"][0]
print(creditScore) # <-- Output: 815
I'm trying to optimize a nested for-loop with filtering, the code looks like:
user_ids = ['A', 'B', 'C']
all_dict_1 = [
{
'id': 'all',
'user_id': 'B',
},
{
'id': 'foo',
'user_id': 'B',
},
{
'id': 'bar',
'user_id': 'A',
},
{
'id': 'bar',
'user_id': 'D',
},
]
all_dict_2 = [
{
'id': 'all',
'percentage': 0.2,
},
{
'id': 'foo',
'percentage': 0.3,
},
]
def _filter(dict_1, dict_2, user_ids):
if str(dict_1['user_id']) in user_ids:
if dict_2['id'] == 'all':
dict_1['percentage'] = dict_2['percentage']
return dict_1
if dict_1['id'] == dict_2['id']:
dict_1['percentage'] = dict_2['percentage']
return dict_1
return None
hits = [_filter(x, y, user_ids) for x in all_dict_1 for y in all_dict_2]
hits = [i for i in hits if i] # Removing None values
the all_dict_1 list is particularly long (thousands of objects), so the function takes more than 1s to run 😕
Are there any libraries or technics to make it quicker?
The logic in your question can be reduced to the following list-comprehension, which should be slightly faster:
>>> hits = [{**x, 'percentage': y['percentage']}
for x in all_dict_1 for y in all_dict_2
if x['user_id'] in user_ids and
(y['id'] == 'all' or x['id'] == y['id'])]
>>> hits
[{'id': 'all', 'user_id': 'B', 'percentage': 0.2},
{'id': 'foo', 'user_id': 'B', 'percentage': 0.2},
{'id': 'foo', 'user_id': 'B', 'percentage': 0.3},
{'id': 'bar', 'user_id': 'A', 'percentage': 0.2}]
Make user_ids a set to speed up item in user_ids tests. Filter with this first, since it rejects entries that you don't have to process at all. Use filter to avoid repeated global name lookups.
user_ids = {'A', 'B', 'C'}
filtered_dict_1 = filter(
lambda item, ids=user_ids: item['user_id'] in ids,
all_dict_1
)
Change all_dict_2 into an actual dict to allow O(1) access instead of O(n) scanning. When iterating over your entries to change them, directly access the required percentage or use an explicit default.
all_dict_2 = {
'foo': 0.3,
}
def add_percentage(item, default=0.2, percentages=all_dict_2):
item["percentage"] = percentages.get(item['id'], default)
return item
Apply the transformation using map to avoid repeated lookups of your transformation function.
hits = list(map(add_percentage, filtered_dict_1))
I have a list of dictionaries,
list = [
{'hostname': 'a', 'ipaddr':'abcde'},
{'hostname': 'a', 'ipaddr':'fghijkl'},
{'hostname': 'a', 'ipaddr':'bbbbbb'},
{'hostname': 'b', 'ipaddr':'xxxx'}
]
How do I make it so that the output looks like this:
outputList = [
{
'hostname': 'a',
'ipaddr': ['abcde', 'fghijkl', 'bbbbbb']
},
{
'hostname': 'b',
'ipaddr':'xxxx'
}
]
Edit:
Before this step, I have filtered a JSON list of selected hostnames
['hostname1', 'hostname2', 'hostname3', 'hostname4' ......]
Then, given a huge JSON list of dictionaries (called "list" above), I have to sieve out the respective hostnames and ipaddresses, preferably grouped according to hostnames so that I can parse it elsewhere easily.
Here is one way:
inputList = [
{'hostname': 'a', 'ipaddr':'abcde'},
{'hostname': 'a', 'ipaddr':'fghijkl'},
{'hostname': 'a', 'ipaddr':'bbbbbb'},
{'hostname': 'b', 'ipaddr':'xxxx'}
]
outputList = {}
for d in inputList:
od = outputList.setdefault(d['hostname'], {})
od.setdefault('hostname', d['hostname'])
od.setdefault('ipaddr', []).append(d['ipaddr'])
outputList = sorted(outputList.values(), key=lambda x: x['hostname'])
assert outputList == [
{
'hostname': 'a',
'ipaddr': ['abcde', 'fghijkl', 'bbbbbb']
},
{
'hostname': 'b',
'ipaddr':['xxxx']
}
]
lists = [
{'hostname': 'a', 'ipaddr':'abcde'},
{'hostname': 'a', 'ipaddr':'fghijkl'},
{'hostname': 'a', 'ipaddr':'bbbbbb'},
{'hostname': 'b', 'ipaddr':'xxxx'}
]
hostnames = set([d['hostname'] for d in lists])
outputlist= list()
for hostname in hostnames:
od = {
'hostname': hostname,
'ipaddr': []
}
for d in lists:
if d['hostname'] == hostname:
od['ipaddr'].append(d['ipaddr'])
outputlist.append(od)
This solution assumes that all the dictionaries inside lists will contain the key 'hostname'.
You can use below code:
list_1 = [
{'hostname': 'a', 'ipaddr':'abcde'},
{'hostname': 'a', 'ipaddr':'fghijkl'},
{'hostname': 'a', 'ipaddr':'bbbbbb'},
{'hostname': 'b', 'ipaddr':'xxxx'}
]
out_list = []
for each_dict in list_1:
if out_list:
for out_dict in out_list:
if out_dict['hostname']==each_dict['hostname']:
out_dict['ipaddr'].append(each_dict['ipaddr'])
else:
temp_dict = {}
temp_dict['hostname']=each_dict['hostname']
temp_dict['ipaddr']=[each_dict['ipaddr'],]
out_list.append(temp_dict)
else:
temp_dict = {}
temp_dict['hostname']=each_dict['hostname']
temp_dict['ipaddr']=[each_dict['ipaddr'],]
out_list.append(temp_dict)
print out_list
from collections import defaultdict
lst = [
{'hostname': 'a', 'ipaddr':'abcde'},
{'hostname': 'a', 'ipaddr':'fghijkl'},
{'hostname': 'a', 'ipaddr':'bbbbbb'},
{'hostname': 'b', 'ipaddr':'xxxx'}
]
d = defaultdict(list)
for item in lst:
d[item['hostname']].append(item['ipaddr'])
output = [dict(zip(['hostname', 'ipaddr'], item)) for item in d.items()]