Combine some items in list [closed] - python

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 12 months ago.
Improve this question
I have list like this,
arr = [{"type":"A","name":"1"},
{"type":"B","name":"2"},
{"type":"B","name":"3"},
{"type":"C","name":"4"},
{"type":"B","name":"5"},
{"type":"B","name":"6"},
{"type":"D","name":"7"},
{"type":"B","name":"8"},
{"type":"B","name":"9"},]]
I want to combine type B like this below
Adding pages key
[{"type":"A","name":"1"},
{"type":"B","pages":[
{"type":"B","name":"2"},
{"type":"B","name":"3"}]},
{"type":"C","name":"4"},
{"type":"B","pages":[
{"type":"B","name":"5"},
{"type":"B","name":"6"}
]},
{"type":"D","name":"7"},
{"type":"B","pages":[
{"type":"B","name":"8"},
{"type":"B","name":"9"}
]}
]
I try to do this with loop,
However, still struggling..
Please give me some ideas.
result = []
first = False
for i in arr:
if i['type'] == "B":
if first == False:
first = True
i['pages'] = []
i['pages'].append(i)
else:
i['pages'].append(i)
else:
result.append(i)
flg = False
print(result)

Here's a solution using itertools.groupby:
from itertools import groupby
result = []
for key, group in groupby(arr, key=lambda x: x['type']):
group = list(group)
if len(group) > 1:
result.append({'type': key, 'pages': group})
else:
result.append(group[0])
from pprint import pprint
pprint(result)
Output:
[{'name': '1', 'type': 'A'},
{'pages': [{'name': '2', 'type': 'B'}, {'name': '3', 'type': 'B'}],
'type': 'B'},
{'name': '4', 'type': 'C'},
{'pages': [{'name': '5', 'type': 'B'}, {'name': '6', 'type': 'B'}],
'type': 'B'},
{'name': '7', 'type': 'D'},
{'pages': [{'name': '8', 'type': 'B'}, {'name': '9', 'type': 'B'}],
'type': 'B'}]

Related

Build a dictionary with single elements or lists as values

I have a list of dictionaries:
mydict = [
{'name': 'test1', 'value': '1_1'},
{'name': 'test2', 'value': '2_1'},
{'name': 'test1', 'value': '1_2'},
{'name': 'test1', 'value': '1_3'},
{'name': 'test3', 'value': '3_1'},
{'name': 'test4', 'value': '4_1'},
{'name': 'test4', 'value': '4_2'},
]
I would like to use it to create a dictionary where the values are lists or single values depending of number of their occurrences in the list above.
Expected output:
outputdict = {
'test1': ['1_1', '1_2', '1_3'],
'test2': '2_1',
'test3': '3_1',
'test4': ['4_1', '4_2'],
}
I tried to do it the way below but it always returns a list, even when there is just one value element.
outputdict = {}
outputdict.setdefault(mydict.get('name'), []).append(mydict.get('value'))
The current output is:
outputdict = {
'test1': ['1_1', '1_2', '1_3'],
'test2': ['2_1'],
'test3': ['3_1'],
'test4': ['4_1', '4_2'],
}
Do what you have already done, and then convert single-element lists afterwards:
outputdict = {
name: (value if len(value) > 1 else value[0])
for name, value in outputdict.items()
}
You can use a couple of the built-in functions mainly itertools.groupby:
from itertools import groupby
from operator import itemgetter
mydict = [
{'name': 'test1', 'value': '1_1'},
{'name': 'test2', 'value': '2_1'},
{'name': 'test1', 'value': '1_2'},
{'name': 'test1', 'value': '1_3'},
{'name': 'test3', 'value': '3_1'},
{'name': 'test4', 'value': '4_1'},
{'name': 'test4', 'value': '4_2'},
]
def keyFunc(x):
return x['name']
outputdict = {}
# groupby groups all the items that matches the returned value from keyFunc
# in our case it will use the names
for name, groups in groupby(mydict, keyFunc):
# groups will contains an iterator of all the items that have the matched name
values = list(map(itemgetter('value'), groups))
if len(values) == 1:
outputdict[name] = values[0]
else:
outputdict[name] = values
print(outputdict)

Getting Error while Iterating over Dictionary in Python [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
My dictionary is below; I get an error while iterating over it.
mk = {'Incident': {'AlertStatus': 'SLA BREACH',
'Area': 'Test',
'Assignee': 'Incident.Coordinator',
'AssignmentGroup': 'Operating System Support (North America)',
'Category': 'incident',
'Contact': 'ALSTON, LOU',
'Description': ['Test - Request - 1 , Test - Request - 1, Test - '
'Request - 1Test - Request - 1Test - Request - '
'1Test - Request - 1Test - Request - 1Test - '
'Request - 1Test - Request - 1'],
'Impact': '2',
'IncidentID': 'IM10265',
'OpenTime': '2020-04-09T08:16:16+00:00',
'OpenedBy': 'rf',
'Phase': 'Categorization',
'Service': 'CI1001032',
'Source': '2',
'Status': 'Categorize',
'Subarea': 'Test',
'Title': 'Test - Request - 1',
'UpdatedBy': 'rf',
'UpdatedTime': '2020-04-09T08:16:25+00:00',
'Urgency': '3'},
'Messages': [],
'ReturnCode': 0}
def extract_val():
id_data = []
Assignee_data = []
id_datas = [q['Incident']['IncidentID'] for q in mk]
Assignee_datas = [t['Incident']['Assignee'] for t in mk]
print(id_datas)
print(Assignee_datas)
extract_val()
getting error as : TypeError: string indices must be integers
Though I'm using key (Incident) to then the other keys like :(Incident), (Assignee) to extract values, still getting error. Please suggest what I'm missing here
If mk is list of dicts try this.
mk = [{'Incident': {'AlertStatus': 'SLA BR', 'Area': 'Test', 'Assignee': 'Incident.Coordinator','Category': 'incident', 'Contact': 'LU', 'Impact': '2', 'IncidentID': 'IM10265', 'OpenedBy': 'rf', 'Phase': 'OP', 'Service': 'CI102', 'Urgency': '3'}, 'Messages': [], 'ReturnCode': 0}, {'Incident': {'AlertStatus': 'SLA AC', 'Area': 'Test', 'Assignee': 'Cris.Bros', 'AssignGroup': 'FCI', 'Category': 'incident', 'Contact': 'AN', 'Description': ['Test-Request-2'], 'IncidentID': 'IM10266', 'Status': 'WI', 'Subarea': '3', 'Urgency': '1'}, 'Messages': [], 'ReturnCode': 0}]
def extract_val():
id_datas , Assignee_datas = map(list, zip(*[(q['Incident']['IncidentID'], q['Incident']['Assignee']) for q in mk]))
print(id_datas)
print(Assignee_datas)
extract_val()
Output:
['IM10265', 'IM10266']
['Incident.Coordinator', 'Cris.Bros']
Let's print and you'll see your problem...
>>> for q in mk:
... print(q)
...
Incident
Messages
ReturnCode
Wen looping through dict like this, you loop through keys.
But I suppose your problem is that you are excepting to have list of that kind of dictionary objects. If so, your function works as expected.
In the following code line:
id_datas = [q['Incident']['IncidentID'] for q in mk]
You are looping through the keys of the dictionary mk. What you want to do is loop through the items. This can de done using the dict.items() method.
Try the following:
id_datas = [q['Incident']['IncidentID'] for q in mk.items()]
EDIT:
My apologies, here is a solution that works when I try it with your dictionary.
id_datas = [q[1]['IncidentID'] for q in mk.items() if q[0] == 'Incident']
So mk.items() returns a list of tuples. Each tuple is in the format (key, value)
In my example q therefore loops through mk, and if the key q[0] is 'Incident', it returns the 'IncidentID' value from the dictionary returned by q[1].

How to modify the values of a dictionary from a list of dictionaries

I am declaring a method named add_to_cart(db, itemid, quantity). Whenever the method is called, it will look into the database for the session data. Session data contains a list of dictionaries. The purpose of this method is to create a new entry (dictionary) to the list or update the value of existing entry.
Dictionary has the following keys: id, quantity
So far I have developed the following code. First of all after fetching the data from the database, I am matching the itemid with the dictionary key: 'id'. If the itemid does not match with any of the values of the dictionaries, then it will append a new dictionary to that list.
def add_to_cart(db, itemid, quantity):
# ......
row = cursor.fetchone()
if row is not None:
cart = json.loads(row['data'])
for dic in cart:
if str(dic.get("id")) == str(itemid):
dic['quantity'] = int(dic['quantity']) + quantity
data = json.dumps(cart)
# update the 'data' to the database
break
else:
if counter == len(cart):
item = {
'id': itemid,
'quantity': quantity
}
cart.append(item)
data = json.dumps(cart)
# update the 'data' to the database
break
Let the initial cart is like:
[{'id': '40', 'quantity': '2'}, {'id': '41', 'quantity': '5'}]
When I add 1 more of the item 40 to the cart, this should be like:
[{'id': '40', 'quantity': '3'}, {'id': '41', 'quantity': '5'}]
but I am getting :
[{'id': '40', 'quantity': '2'}, {'id': '41', 'quantity': '5'}, {'id': '40', 'quantity': '1'}]
You are adding a new dictionary to the list when you do cart.append(item),
hence the list
[{'id': '40', 'quantity': '2'}, {'id': '41', 'quantity': '5'}]
ends up being
[{'id': '40', 'quantity': '2'}, {'id': '41', 'quantity': '5'}, {'id': '40', 'quantity': '1'}]
But you want to find the matching id in that list of dictionaries, and add to the quantity for that dictionary.
So the code will look like as below:
li = [{'id': '40', 'quantity': '2'}, {'id': '41', 'quantity': '5'}]
def add_elem(li, id, to_add):
#Iterate over the dictionaries
for item in li:
#If the id is found
if str(id) in item.values():
#Increment the quantity
item['quantity'] = str(int(item['quantity']) + to_add)
#Return the updated list
return li
print(add_elem(li, 40, 1))
The output will be
[{'id': '40', 'quantity': '3'}, {'id': '41', 'quantity': '5'}]
The problem seems to be that you are going simply adding a new dict to the list (cart), through append. You need to go through the list, find the dict with the itemid you need, then add to the quantity.
Try this -
for dict in cart:
if dict[itemid] == itemid:
dict['quantity'] += str(quantity)
break
item = {
'id': itemid,
'quantity': quantity
}
cart.append(item)

Filling in the list of the required format in the python loop

I am trying to create a list structure in a loop:
[children:[{text: "Title 1", id: '1', expanded: true,children: [{text: "title2", leaf: true ,},{text: "title3", leaf: true}]},{text: "Title4", id: '4', expanded: true, children: [{text: "title5", leaf: true,} ]}]]
The source data looks like this:
mylist =[{'id': '1', 'name': 'Title1', 'id_parent': '0'}, {'id': '2', 'name': 'title2', 'id_parent': '1'}, {'id': '3', 'name': 'title3', 'id_parent': '1'}, {'id': '4', 'name': 'Title4', 'id_parent': '0'}, {'id': '5', 'name': 'title5', 'id_parent': '4'}]
Using recursion, I go through the data and get parental and childish records:
def get_parent(id_parent):
c = []
for x in mylist:
if not x["id"] == id_parent and x["id_parent"] == id_parent:
if x["id_parent"] == id_parent:
x['expanded'] = True
else:
x['leaf'] = True
c.append(x)
return(c)
def get_tree(t):
lst = []
main_data = []
for x in get_parent(t):
all_stor = {}
all_stor["text"] = x['name']
all_stor["id"] = x['id']
if x.get('expanded'):
all_stor["expanded"] = x['expanded']
else:
all_stor["leaf"] = x['leaf']
main_data.append(all_stor)
lst.append([main_data, get_tree(x["id"])])
return lst
main = get_tree("0")
print(main)
How to fill the main_data list in a loop in order to get the necessary structure?
Your expected output should be a list of children from the root level:
def get_tree(l, parent='0'):
children = []
for d in l:
if d['id_parent'] == parent:
details = {'text': d['name'], 'id': d['id']}
grand_children = get_tree(l, d['id'])
if grand_children:
details.update({'expanded': True, 'children': grand_children})
else:
details['leaf'] = True
children.append(details)
return children
so that with your sample input, get_tree(mylist) would return:
[{'text': 'Title1', 'id': '1', 'expanded': True, 'children': [{'text': 'title2', 'id': '2', 'leaf': True}, {'text': 'title3', 'id': '3', 'leaf': True}]}, {'text': 'Title4', 'id': '4', 'expanded': True, 'children': [{'text': 'title5', 'id': '5', 'leaf': True}]}

compare two different length lists of dictionaries in python

I want to compare below dictionaries. Name key in the dictionary is common in both dictionaries.
If Name matched in both the dictionaries, i wanted to do some other stuff with the data.
PerfData = [
{'Name': 'abc', 'Type': 'Ex1', 'Access': 'N1', 'perfStatus':'Latest Perf', 'Comments': '07/12/2017 S/W Version'},
{'Name': 'xyz', 'Type': 'Ex1', 'Access': 'N2', 'perfStatus':'Latest Perf', 'Comments': '11/12/2017 S/W Version upgrade failed'},
{'Name': 'efg', 'Type': 'Cust1', 'Access': 'A1', 'perfStatus':'Old Perf', 'Comments': '11/10/2017 S/W Version upgrade failed, test data is active'}
]
beatData = [
{'Name': 'efg', 'Status': 'Latest', 'rcvd-timestamp': '1516756202.632'},
{'Name': 'abc', 'Status': 'Latest', 'rcvd-timestamp': '1516756202.896'}
]
Thanks
Rajeev
l = [{'name': 'abc'}, {'name': 'xyz'}]
k = [{'name': 'a'}, {'name': 'abc'}]
[i['name'] for i in l for f in k if i['name'] == f['name']]
Hope above logic work for you.
The answer provided didn't assign the result to any variable. If you want to print it, add the following would work:
result = [i['name'] for i in l for f in k if i['name'] == f['name']]
print(result)

Categories