Python controlling the output "print" - python

all_path = [[[2, 3, 4, 5], [2, 4, 5], [2, 5]],
[[2, 3, 4, 5], [2, 4, 5], [2, 5]],
[[2, 3, 4, 5], [2, 4, 5], [2, 5]],
[[4, 5]],
[[1, 2, 3, 4, 5], [1, 2, 4, 5], [1, 2, 5]]]
s_dict = {1: {'Origin': '002', 'Destination': '005', 'Cost': '0000.00', 'Stops': '99', 'Time': '00.00'},
2: {'Origin': '002', 'Destination': '005', 'Cost': '0000.00', 'Stops': '11', 'Time': '00.00'},
3: {'Origin': '002', 'Destination': '005', 'Cost': '1450.11', 'Stops': '99', 'Time': '00.00'},
4: {'Origin': '004', 'Destination': '005', 'Cost': '1550.11', 'Stops': '99', 'Time': '22.22'},
5: {'Origin': '001', 'Destination': '005', 'Cost': '0000.00', 'Stops': '99', 'Time': '11.00'}}
for tin in range(1,6):
print 'From: '+str(int(s_dict[tin]['Origin']))+','+' to: '+str(int((s_dict[tin]['Destination'])))+','+' Stops: '+(s_dict[tin]['Stops'])+','+' Cost: '+(s_dict[tin]['Cost'])+','+' Time: '+(s_dict[tin]['Time'])
print 'All routes:'
for n in range(len(all_path[tin-1])):
l=''
for s in range(len(all_path[tin-1][n])):
l+= str(all_path[tin-1][n][s])+'->'
print l
and this is the output,
I will quote one part
From: 2, to: 5, Stops: 99, Cost: 0000.00, Time: 00.00
All routes:
2->3->4->5->
2->4->5->
2->5->
my problem is that extra ' -> '
at the end of the line
I want it to be something more like
2->3->4->5
is there a way to not show "an extra" ' -> ' at the end?

Take a look at the join-method:
print '->'.join(str(x) for x in all_path[tin-1][n])
# print '->'.join(map(str, all_path[tin-1][n]))
> print '->'.join(['1', '2', '3']) # '->'.join('123')
1->2->3

Related

How to convert this loops into list comprehension?

I want to convert these loops into a list comprehension but I don't know how to do it. Can anyone help me pls?
this is the list i want to convert:
students = ['Tommy', 'Kitty', 'Jessie', 'Chester', 'Curie', 'Darwing', 'Nancy', 'Sue',
'Peter', 'Andrew', 'Karren', 'Charles', 'Nikhil', 'Justin', 'Astha','Victor',
'Samuel', 'Olivia', 'Tony']
assignment = [2, 5, 5, 7, 1, 5, 2, 7, 5, 1, 1, 1, 2, 1, 5, 2, 7, 2, 7]
x = list(zip(students, assignment))
Output = {}
for ke, y in x:
y = "Group {}".format(y)
if y in Output:
Output[y].append((ke))
else:
Output[y] = [(ke)]
print(Output)
this what I have tried:
{Output[y].append((ke)) if y in Output else Output[y]=[(ke)]for ke, y in x}
You could do this with a nested dictionary/list comprehension:
Output = { f'Group {group}' : [ name for name, g in x if g == group ] for group in set(assignment) }
Output:
{
'Group 2': ['Tommy', 'Nancy', 'Nikhil', 'Victor', 'Olivia'],
'Group 5': ['Kitty', 'Jessie', 'Darwing', 'Peter', 'Astha'],
'Group 7': ['Chester', 'Sue', 'Samuel', 'Tony'],
'Group 1': ['Curie', 'Andrew', 'Karren', 'Charles', 'Justin']
}
data1 = {'students': ['Tommy', 'Kitty', 'Jessie', 'Chester', 'Curie', 'Darwing', 'Nancy', 'Sue',
'Peter', 'Andrew', 'Karren', 'Charles', 'Nikhil', 'Justin', 'Astha','Victor',
'Samuel', 'Olivia', 'Tony'],
'assignment': [2, 5, 5, 7, 1, 5, 2, 7, 5, 1, 1, 1, 2, 1, 5, 2, 7, 2, 7]}
df1 = pd.DataFrame(data1)
df1.groupby('assignment')['students'].agg(set).to_dict()
Output
{1: {'Andrew', 'Charles', 'Curie', 'Justin', 'Karren'},
2: {'Nancy', 'Nikhil', 'Olivia', 'Tommy', 'Victor'},
5: {'Astha', 'Darwing', 'Jessie', 'Kitty', 'Peter'},
7: {'Chester', 'Samuel', 'Sue', 'Tony'}}
You want a dict comprehension which will create a dict whose values come from a list comprehension.
itertools.groupby can help:
from itertools import groupby
x = sorted(list(zip(assignment, students)))
out = {f'Group {x}':[z[1] for z in y] for x,y in groupby(x, lambda y:y[0])}
{'Group 1': ['Andrew', 'Charles', 'Curie', 'Justin', 'Karren'], 'Group 2': ['Nancy', 'Nikhil', 'Olivia', 'Tommy', 'Victor'], 'Group 5': ['Astha', 'Darwing', 'Jessie', 'Kitty', 'Peter'], 'Group 7': ['Chester', 'Samuel', 'Sue', 'Tony']}

Problem inputting several lists to dictionary values

Stackoverflow, hello
I have a big problem with inputting a several list into multiple values
Initial code is:
animal_book={}
animal_type=['herbivorous', 'carnivorous']
animal_name=[['Elephant', 'Cow', 'Deer'], ['Tiger', 'Lion', 'Puma']]
animal_quantity=[[1, 2, 3], [4, 5, 6]]
animal_age=[['50','10','5'],['6', '7', '8']]
j=0
k=0
for i in animal_type:
animal_book[i]=[{'type':animal_name[j][k], 'name': animal_quantity[j][k], 'age':animal_age[j][k]}]
j += 1
print(animal_book)
The result I have is almost what I need, but with only one first compound in a animal_book value, not the several dictionaries, as I wanted (I've separated it by lines manually for better look):
>>{'herbivorous': [
{'name': 'Elephant', 'quantity': 1, 'age': '50'}
],
'carnivorous': [
{'name': 'Tiger', 'quantity': 4, 'age': '6'}
]
}
However, my aim here is to put these list into multiple values of the dictionary. Required code is:
{'herbivorous': [
{'name': 'Elephant', 'quantity': 1, 'age': '50'},
{'name': 'Cow', 'quantity': 2, 'age': '10'},
{'name': 'Deer', 'quantity': 3, 'age': '5'},
],
'carnivorous':[
{'name': 'Tiger', 'quantity': 4, 'age': '6'}
{'name': 'Lion', 'quantity': 5, 'age': '7'}
{'name': 'Puma', 'quantity': 6, 'age': '8'}
]
}
Does everybody know how to solve the problem?
I've tried to add the lists to animal_book.values() also after the for i in animal_type:
animal_book[i]=animal_book.values().append([{'name':animal_name[j][k], 'quantity': animal_quantity[j][k], 'age':animal_age[j][k]}])
But in this case I have an error: AttributeError: 'dict_values' object has no attribute 'append'
First Mistake :you are getting only one result because you are over-writing the dictionary value each time with the list .
Second Mistake : You are increasing j by one and looping through the animal type list which has 2 elements that means only two elements will be in the dictionary.
from pprint import pprint
animal_book={}
animal_type=['herbivorous', 'carnivorous']
animal_name=[['Elephant', 'Cow', 'Deer'], ['Tiger', 'Lion', 'Puma']]
animal_quantity=[[1, 2, 3], [4, 5, 6]]
animal_age=[['50','10','5'],['6', '7', '8']]
for j in range(len(animal_type)):
value_list = []
for k in range(len(animal_name[j])):
value_list.append({'type':animal_quantity[j][k], 'name': animal_name[j][k], 'age':animal_age[j][k]})
animal_book.update({animal_type[j]: value_list})
pprint(animal_book)
Output:
{'carnivorous': [{'age': '6', 'name': 'Tiger', 'type': 4},
{'age': '7', 'name': 'Lion', 'type': 5},
{'age': '8', 'name': 'Puma', 'type': 6}],
'herbivorous': [{'age': '50', 'name': 'Elephant', 'type': 1},
{'age': '10', 'name': 'Cow', 'type': 2},
{'age': '5', 'name': 'Deer', 'type': 3}]}
You can use zip to arrange your data in a suiteable manner and fill your book with that:
animal_book ={}
animal_type=['herbivorous', 'carnivorous']
animal_name=[['Elephant', 'Cow', 'Deer'], ['Tiger', 'Lion', 'Puma']]
animal_quantity=[[1, 2, 3], [4, 5, 6]]
animal_age=[['50','10','5'],['6', '7', '8']]
# zip your data together, extract the typ again, put the remainder into R
for typ, *R in zip(animal_type, animal_name, animal_quantity, animal_age):
# add the typ-list
animal_book.setdefault(typ,[])
# now handle the inner dicts data that have to be added to your lists
# first create tuples for each animal as r
for r in zip(*R):
# then create tuples of (key,value) and make dicts from it
animal_book[typ].append(dict(zip(["name","quantity","age"],r)))
# pretty print it
from pprint import pprint
pprint(animal_book)
Output:
{'carnivorous': [{'age': '6', 'name': 'Tiger', 'quantity': 4},
{'age': '7', 'name': 'Lion', 'quantity': 5},
{'age': '8', 'name': 'Puma', 'quantity': 6}],
'herbivorous': [{'age': '50', 'name': 'Elephant', 'quantity': 1},
{'age': '10', 'name': 'Cow', 'quantity': 2},
{'age': '5', 'name': 'Deer', 'quantity': 3}]}
R looks like this:
[['Elephant', 'Cow', 'Deer'], [1, 2, 3], ['50', '10', '5']]
[['Tiger', 'Lion', 'Puma'], [4, 5, 6], ['6', '7', '8']]
and r look like this:
('Elephant', 1, '50')
('Cow', 2, '10')
('Deer', 3, '5')
('Tiger', 4, '6')
('Lion', 5, '7')
('Puma', 6, '8')
and zip(["name","quantity","age"],r) looks approximately like so:
[('name', 'Elephant'), ('quantity', 1), ('age', '50')]
[('name', 'Cow'), ('quantity', 2), ('age', '10')]
[('name', 'Deer'), ('quantity', 3), ('age', '5')]
[('name', 'Tiger'), ('quantity', 4), ('age', '6')]
[('name', 'Lion'), ('quantity', 5), ('age', '7')]
[('name', 'Puma'), ('quantity', 6), ('age', '8')]
Here you go, this solves your problem. You have to have one for loop nested inside another one and use enumerate so you can keep track of the index. Also, if you use json.dumps() it will pretty-print a dictionary for you.
import json
animal_type=['herbivorous', 'carnivorous']
animal_name=[['Elephant', 'Cow', 'Deer'], ['Tiger', 'Lion', 'Puma']]
animal_quantity=[[1, 2, 3], [4, 5, 6]]
animal_age=[['50','10','5'],['6', '7', '8']]
animal_book={}
for index, type in enumerate(animal_type):
animal_book[type] = []
for jdex, animal in enumerate(animal_name[index]):
animal_book[type].append({
'name': animal,
'quantity': animal_quantity[index][jdex],
'age': animal_age[index][jdex],
})
print(json.dumps(animal_book, indent=2))
This will output:
{
"herbivorous": [
{
"name": "Elephant",
"quantity": 1,
"age": "50"
},
{
"name": "Cow",
"quantity": 2,
"age": "10"
},
{
"name": "Deer",
"quantity": 3,
"age": "5"
}
],
"carnivorous": [
{
"name": "Tiger",
"quantity": 4,
"age": "6"
},
{
"name": "Lion",
"quantity": 5,
"age": "7"
},
{
"name": "Puma",
"quantity": 6,
"age": "8"
}
]
}
You should use the range function to iterate over the items in more systematic way:
animal_book={}
animal_type=['herbivorous', 'carnivorous']
animal_name=[['Elephant', 'Cow', 'Deer'], ['Tiger', 'Lion', 'Puma']]
animal_quantity=[[1, 2, 3], [4, 5, 6]]
animal_age=[['50','10','5'],['6', '7', '8']]
for i in range(len(animal_type)):
for j in range(len(animal_name[i])):
animal_book[i]=[{'type':animal_name[i][j], 'name': animal_quantity[i][j], 'age':animal_age[i][j]}]
print(animal_book)

Separate list elements by theirs property in Python

I have list p1:
p1 = [
{'id': 1, 'area': 5},
{'id': 2, 'area': 6},
{'id': 3, 'area': 10},
{'id': 4, 'area': 6},
{'id': 5, 'area': 6},
{'id': 6, 'area': 6},
{'id': 7, 'area': 4},
{'id': 8, 'area': 4}
]
And I need to separate this list by area value, like this (p2):
p2 = {
4: [
{'id': 7, 'area': 4},
{'id': 8, 'area': 4}
],
5: [
{'id': 1, 'area': 5}
],
6: [
{'id': 2, 'area': 6},
{'id': 4, 'area': 6},
{'id': 5, 'area': 6},
{'id': 6, 'area': 6}
],
10: [
{'id': 3, 'area': 10}
]
}
My solution is:
areas = {x['area'] for x in p1}
p2 = {}
for area in areas:
p2[area] = [x for x in p1 if x['area'] == area]
It seems to work, but is there any better and more "pythonic" solution?
Using groupby you get
>>> import itertools
>>> f = lambda t: t['area']
>>> {i: list(b) for i, b in itertools.groupby(sorted(p1, key=f), key=f)}
Gives
{4: [{'area': 4, 'id': 7},
{'area': 4, 'id': 8}],
5: [{'area': 5, 'id': 1}],
6: [{'area': 6, 'id': 2},
{'area': 6, 'id': 4},
{'area': 6, 'id': 5},
{'area': 6, 'id': 6}],
10: [{'area': 10, 'id': 3}]}
edit: If you don't like using lambdas you can also do, as suggested by bro-grammer
>>> import operator
>>> f = operator.itemgetter('area')
You can simply use defaultdict:
from collections import defaultdict
result = defaultdict(list)
for i in p1:
result[i['area']].append(i)
Yes, use one of the grouping idioms. Using a vanilla dict:
In [15]: p1 = [
...: {'id': 1, 'area': 5},
...: {'id': 2, 'area': 6},
...: {'id': 3, 'area': 10},
...: {'id': 4, 'area': 6},
...: {'id': 5, 'area': 6},
...: {'id': 6, 'area': 6},
...: {'id': 7, 'area': 4},
...: {'id': 8, 'area': 4}
...: ]
In [16]: p2 = {}
In [17]: for d in p1:
...: p2.setdefault(d['area'], []).append(d)
...:
In [18]: p2
Out[18]:
{4: [{'area': 4, 'id': 7}, {'area': 4, 'id': 8}],
5: [{'area': 5, 'id': 1}],
6: [{'area': 6, 'id': 2},
{'area': 6, 'id': 4},
{'area': 6, 'id': 5},
{'area': 6, 'id': 6}],
10: [{'area': 10, 'id': 3}]}
Or more neatly, using a defaultdict:
In [23]: from collections import defaultdict
In [24]: p2 = defaultdict(list)
In [25]: for d in p1:
...: p2[d['area']].append(d)
...:
In [26]: p2
Out[26]:
defaultdict(list,
{4: [{'area': 4, 'id': 7}, {'area': 4, 'id': 8}],
5: [{'area': 5, 'id': 1}],
6: [{'area': 6, 'id': 2},
{'area': 6, 'id': 4},
{'area': 6, 'id': 5},
{'area': 6, 'id': 6}],
10: [{'area': 10, 'id': 3}]})

Updating a MongoDB document with PyMongo

I am trying to update a document in a collection:
for bookerName,bookingId in zip(bookerNames,bookingIds):
Person.update_one({'Name': bookerName}, {'$push': {'Bookings': bookingId}})
I am trying to add a new bookingId to the list of Bookings this Person already has.
I receive the following error:
bson.errors.InvalidDocument: Cannot encode object: 0
From what I understand about this error, it means Mongo don't know how to encode a list, it treats it as a custom type.
However, this is strange since I can do:
for bookerName in BookerNames:
personRecord = {"Name":bookerName,"Bookings":[1,2,3,4]}
Person.insert_one(personRecord)
And it works perfectly.
I have also tried to update using $set and even by deleting the old record and trying to insert a new one with the updated list.
Any idea why this is happening or how can I update a list in a document?
I am using Python 3.5, PyMongo 3.0.3 and MongoDB 3.0.7. Could the difference in version between PyMongo and MondoDB be the issue?
EDIT:
for bookerName in bookerNames:
bookingList = bookersToBookings[bookerName]
personRecord = {"Name":bookerName,"Bookings":bookingList}
Person.insert_one(personRecord)
Where bookersToBookings is a dictionary mapping bookers to their bookingIds, as list.
This does not work, although if I make a record with a list like [1,2,3], it works.
EDIT 2:
for bookerName in bookerNames:
personRecord = {"Name":bookerName,"Bookings":[]}
Person.insert_one(personRecord)
for x in Person.find():
print(x)
This works. It prints:
{'Name': 'Alice', '_id': ObjectId('56241ad79e44c71641efa383'), 'Bookings': []}
{'Name': 'John', '_id': ObjectId('56241ad79e44c71641efa384'), 'Bookings': []}
{'Name': 'Jane', '_id': ObjectId('56241ad79e44c71641efa385'), 'Bookings': []}
{'Name': 'Mary', '_id': ObjectId('56241ad79e44c71641efa386'), 'Bookings': []}
{'Name': 'Dan', '_id': ObjectId('56241ad79e44c71641efa387'), 'Bookings': []}
This also works:
for bookerName in bookerNames:
personRecord = {"Name":bookerName,"Bookings":[1,2,3]}
Person.insert_one(personRecord)
Result:
{'Bookings': [1, 2, 3], '_id': ObjectId('56241b029e44c716497b60b2'), 'Name': 'Alice'}
{'Bookings': [1, 2, 3], '_id': ObjectId('56241b029e44c716497b60b3'), 'Name': 'John'}
{'Bookings': [1, 2, 3], '_id': ObjectId('56241b029e44c716497b60b4'), 'Name': 'Jane'}
{'Bookings': [1, 2, 3], '_id': ObjectId('56241b029e44c716497b60b5'), 'Name': 'Mary'}
{'Bookings': [1, 2, 3], '_id': ObjectId('56241b029e44c716497b60b6'), 'Name': 'Dan'}
Even this works:
for bookerName in bookerNames:
y = [1,2,3,4]
personRecord = {"Name":bookerName,"Bookings":[x for x in y]}
Person.insert_one(personRecord)
Result:
{'_id': ObjectId('56241b5a9e44c7165395a0f0'), 'Bookings': [1, 2, 3, 4], 'Name': 'Alice'}
{'_id': ObjectId('56241b5a9e44c7165395a0f1'), 'Bookings': [1, 2, 3, 4], 'Name': 'John'}
{'_id': ObjectId('56241b5a9e44c7165395a0f2'), 'Bookings': [1, 2, 3, 4], 'Name': 'Jane'}
{'_id': ObjectId('56241b5a9e44c7165395a0f3'), 'Bookings': [1, 2, 3, 4], 'Name': 'Mary'}
{'_id': ObjectId('56241b5a9e44c7165395a0f4'), 'Bookings': [1, 2, 3, 4], 'Name': 'Dan'}
This, however, does not work:
for bookerName in bookerNames:
y = bookersToBookings[bookerName]
personRecord = {"Name":bookerName,"Bookings":[x for x in y]}
Person.insert_one(personRecord)
bookersToBookings looks like this:
{'Mary': [5, 9], 'Jane': [4, 7, 8, 13, 14], 'Alice': [0, 6, 10], 'Dan': [12], 'John': [1, 2, 3, 11]}
EDIT 3 - SOLVED:
For $%#^ sake! The list was made of numpy64 ints, not python ints. It works now.
Thanks for the help!

Sort list by indexes of another list?

I have a dictionary of dictionaries. Within these subdictionaries, I have two keys - ui_section and section_order - that determine if the value of this subdictionary is shown in a specfic portion of the UI and if so, what order it appears. My dictionary looks like this:
MASTER_DICT = {
'key1': {'ui_section':[1,2],'section_order':1, 'value': 'key1'},
'key2': {'ui_section':[1],'section_order':2, 'value': 'key2'},
'key3': {'ui_section':[1,2],'section_order':3, 'value': 'key3'},
'key4': {'ui_section':[1],'section_order':4, 'value': 'key4'},
'key5': {'ui_section':[1],'section_order':5, 'value': 'key5'},
'key6': {'ui_section':[1],'section_order':6, 'value': 'key6'},
'key7': {'ui_section':[1],'section_order':7, 'value': 'key7'},
'key8': {'ui_section':[1],'section_order':8, 'value': 'key8'},
'key9': {'ui_section':[1],'section_order':9, 'value': 'key9'},
}
The ui_section is a list of possible sections the key can appear in. I determine this via the following code:
def show_section_ui(master_dict, section=None):
if section:
ui_sections = []
# Find the keys that are part of this section
for k in master_dict.keys():
try:
if section in master_dict[k]['ui_section']:
ui_sections.append(master_dict[k])
except AttributeError:
pass
# Order the keys by sort order
ui_sections.sort(key=lambda x: x['section_order'])
return ui_sections
else:
return None
This portion of the code works. The output below shows that order is correct for both sections 1 and 2.
>>> pprint.pprint(show_section_ui(MASTER_DICT, 1))
[{'section_order': 1, 'ui_section': [1,2], 'value': 'key1'},
{'section_order': 2, 'ui_section': [1], 'value': 'key2'},
{'section_order': 3, 'ui_section': [1,2], 'value': 'key3'},
{'section_order': 4, 'ui_section': [1], 'value': 'key4'},
{'section_order': 5, 'ui_section': [1], 'value': 'key5'},
{'section_order': 6, 'ui_section': [1], 'value': 'key6'},
{'section_order': 7, 'ui_section': [1], 'value': 'key7'},
{'section_order': 8, 'ui_section': [1], 'value': 'key8'},
{'section_order': 9, 'ui_section': [1], 'value': 'key9'}]
>>> pprint.pprint(show_section_ui(MASTER_DICT, 2))
[{'section_order': 1, 'ui_section': [1,2], 'value': 'key1'},
{'section_order': 3, 'ui_section': [1,2], 'value': 'key3'}]
My problem is that the section_order needs to have sort orders per ui_section. For example, in the above outputs, in section 2, I'd like key3 to be first. My initial thought was to make section_order a list as well. But, I'm not sure how to adjust this line to properly account for the list (and to select the correct index to sort by then)
ui_sections.sort(key=lambda x: x['section_order'])
My intention was to do something like this:
MASTER_DICT = {
'key1': {'ui_section':[1,2],'section_order':[1,2], 'value': 'key1'},
'key2': {'ui_section':[1],'section_order':[2], 'value': 'key2'},
'key3': {'ui_section':[1,2],'section_order':[3,1], 'value': 'key3'},
}
Getting me output like this:
>>> pprint.pprint(show_section_ui(MASTER_DICT, 2))
[{'section_order': [3,1], 'ui_section': [1,2], 'value': 'key3'},
{'section_order': [1,2], 'ui_section': [1,2], 'value': 'key1'}]
How can I sort by the ui_section and the appropriate index within the key?
I think I understood. If you want to sort a list of items according to the order of another list of items, you could do something like this. Step by step, the last line is what need.
We need itertools.count(), which is an infinite incrementing range, used to apply an index.
import itertools
these should be sorted by 'value'
>>> values = [{"name": "A", "value": 10},
{"name": "B", "value": 8},
{"name": "C", "value": 9}]
these are in the same input order as values, and should be sorted in the the same order
>>> to_sort = [{"name": "A", "payload": "aaa"},
{"name": "B", "payload": "bbb"},
{"name": "C", "payload": "ccc"}]
Zip the values with their indexes. This annotates each item to include its original order. This is a list of pairs of (object, index)
>>> zip(values, itertools.count())
[({'name': 'A', 'value': 10}, 0),
({'name': 'B', 'value': 8}, 1),
({'name': 'C', 'value': 9}, 2)]
Now sort by the key 'value'. The x[0] is to get the first item of the pair (the object).
>>> sorted(zip(values, itertools.count()), key=lambda x: x[0]["value"])
[({'name': 'B', 'value': 8}, 1),
({'name': 'C', 'value': 9}, 2),
({'name': 'A', 'value': 10}, 0)]
Now retrieve the indexes from the pairs to return the new order of the original indexes.
>>> map(lambda x: x[1],
sorted(zip(values, itertools.count()),
key=lambda x: x[0]["value"]))
[1, 2, 0]
Now use those indexes to map over the to_sort list and retrieve the items at those indexes.
>>> map(lambda i: to_sort[i],
map(lambda x: x[1],
sorted(zip(values, itertools.count()),
key=lambda x: x[0]["value"])))
[{'name': 'B', 'payload': 'bbb'},
{'name': 'C', 'payload': 'ccc'},
{'name': 'A', 'payload': 'aaa'}]
I hope that answers your question. It means changing MASTER_DICT to be a list, but I think that's the best representation for it anyway.
I don't have a nice one line code change for you, but you can replace the line you have:
ui_sections.sort(key=lambda x: x['section_order'])
With this:
sort_orders = []
for s in ui_sections:
ndx = s['ui_section'].index(section)
# This next line makes the assumption that you ALWAYS have a section_order
# for every ui_section listed. If not, you'll get an IndexError
sort_orders.append(s['section_order'][ndx])
# Magic happens here
sorted_sections = [x for y, x in sorted(zip(sort_orders,ui_sections))]
return sorted_sections
Output:
>>> pprint.pprint(show_section_ui(MASTER_DICT, 2))
[{'section_order': [3, 1], 'ui_section': [1, 2], 'value': 'key3'},
{'section_order': [1, 2], 'ui_section': [1, 2], 'value': 'key1'}]
>>> pprint.pprint(show_section_ui(MASTER_DICT, 1))
[{'section_order': [1, 2], 'ui_section': [1, 2], 'value': 'key1'},
{'section_order': [2], 'ui_section': [1], 'value': 'key2'},
{'section_order': [3, 1], 'ui_section': [1, 2], 'value': 'key3'},
{'section_order': [4], 'ui_section': [1], 'value': 'key4'},
{'section_order': [5], 'ui_section': [1], 'value': 'key5'},
{'section_order': [6], 'ui_section': [1], 'value': 'key6'},
{'section_order': [7], 'ui_section': [1], 'value': 'key7'},
{'section_order': [8], 'ui_section': [1], 'value': 'key8'},
{'section_order': [9], 'ui_section': [1], 'value': 'key9'}]
Adding key8 to the second ui_section at position 3, and key7 at position 4:
[{'section_order': [3, 1], 'ui_section': [1, 2], 'value': 'key3'},
{'section_order': [1, 2], 'ui_section': [1, 2], 'value': 'key1'},
{'section_order': [8, 3], 'ui_section': [1, 2], 'value': 'key8'},
{'section_order': [7, 4], 'ui_section': [1, 2], 'value': 'key7'}]
This is utilizing this answer. First, though, it finds the index that the section is listed in the ui_section:
ndx = s['ui_section'].index(section)
The value at this location is then added to the sort_orders list. Note that the code provided does not error check that this is valid (ie. if you don't have a value for the second position), and will throw an IndexError if it is not.
sort_orders.append(s['section_order'][ndx])
Next it zips the two lists together so that you have a list of tuples containing the sort order and the section dictionary.
[(3, {'ui_section': [1, 2], 'section_order': [8, 3], 'value': 'key8'}),
(1, {'ui_section': [1, 2], 'section_order': [3, 1], 'value': 'key3'}),
(2, {'ui_section': [1, 2], 'section_order': [1, 2], 'value': 'key1'}),
(4, {'ui_section': [1, 2], 'section_order': [7, 4], 'value': 'key7'})
]
Then we sort that based on the first position in the tuple. Then we unzip it and pull back the sorted information. All of that occurs in this line:
sorted_sections = [x for y, x in sorted(zip(sort_orders,ui_sections))]

Categories