This question already has answers here:
Finding the index of elements based on a condition using python list comprehension
(6 answers)
Closed 8 days ago.
There is a list:
Aliances=[(1, 'Star Aliance'), (2, 'OneWorld'), (3, 'SkyTeam'), (4, 'Unknown'), (5, 'U-FLY Alliance'), (6, 'SkyTeam Cargo'), (7, 'WOW'), (8, 'Vanilla Alliance'), (9, 'Value Alliance'), (10, 'American Eagle'), (11, 'American Airlines'), (12, 'Sirius Aero'), (10012, 'ASL Aviation Holdings DAC')]
There is a number that is on this list:
PK = 10012
Aliances = S.QueryAliances()
print("Aliances=" + str(Aliances))
myDialog.comboBox_Alliance.clear()
if Aliances:
for Aliance in Aliances:
myDialog.comboBox_Alliance.addItem(str(Aliance[1]))
PKs = []
for PK in Aliances:
PKs.append(PK[0])
print("PKs=" + str(PKs))
quantity = myDialog.comboBox_Alliance.count()
index = PKs.index(A.Aliance)
print("index=" + str(index))
myDialog.comboBox_Alliance.setCurrentIndex(index)
Tell me please if anyone knows how to get "index" (position of PK=10012) directly from list "Aliances"?
Link to Source Code on my GitHub
This is actually not a two-dimensional list, but a list of tuples. However, the following should work:
Aliances=[(1, 'Star Aliance'), (2, 'OneWorld'), (3, 'SkyTeam'), (4, 'Unknown'), (5, 'U-FLY Alliance'), (6, 'SkyTeam Cargo'), (7, 'WOW'), (8, 'Vanilla Alliance'), (9, 'Value Alliance'), (10, 'American Eagle'), (11, 'American Airlines'), (12, 'Sirius Aero'), (10012, 'ASL Aviation Holdings DAC')]
index = next((i for i, x in enumerate(Aliances) if x[0] == 10012), None)
print(index)
Output:
12
This also returns None if no match is found. Adapted from this solution.
Related
I am new in python and for practice reasons, I am trying to solve the following task:
Given a list of tuples
A = [(17, 8), (17, 12), (7, 2), (9, 15), (9, 17), (1, 4), (3, 9), (12, 14)]
My goal is: to sort in (n log n) time in descending order the list according to the first element of the set and if the first element of two sets are the same, sorting in descending order according to the second element. --> x <= x', y <= y'
So, I want to get the result:
A = [(17, 12), (17, 8), (12, 14), (9, 17), (9, 15), (7, 2), (3, 9), (1, 4)]
I have tried using the following code:
A.sort(reverse = True, key=lambda x: x[0] )
But it just sorts according to the first element and I do know if it is in n log n time.
Could you please help me with that?
Thank you!
To sort based on both values, remove the key function:
>>> A.sort(reverse = True)
>>> A
[(17, 12), (17, 8), (12, 14), (9, 17), (9, 15), (7, 2), (3, 9), (1, 4)]
And yes, Python sorts in O(n log n), for more, check out Timsort on Wikipedia, the algorithm Python uses for sorting.
Python's inbuilt sorted() method with a comparator function(Similar to C++) will work
sorted(tup, key = lambda x: x[0])
Tuples are naturally sorted by the first element, then the second:
A.sort(reverse = True)
Output as requested.
There you go:
A = [(17, 8), (17, 12), (7, 2), (9, 15), (9, 17), (1, 4), (3, 9), (12, 14)]
reverse_sorted = []
for item in reversed(sorted(A)):
reverse_sorted.append(item)
print(reverse_sorted)
As to add to the other's excellent answers. Search on Google with "python list sort time complexity" will return for you what you seek regarding python's sort time complexities (that others have already written above).
In addition, if you need to move away from using python's inbuilt sort function. There are many different sorting algorithms created over the years that you can recreate that have the desired time complexities. It would be a good "training" exercise if you're new to programming in general.
This question already has answers here:
How to filter a dictionary according to an arbitrary condition function?
(7 answers)
Closed 4 years ago.
I have dictionary in format "site_mame": (side_id, frequency):
d=[{'fpdownload2.macromedia.com': (1, 88),
'laposte.net': (2, 23),
'www.laposte.net': (3, 119),
'www.google.com': (4, 5441),
'match.rtbidder.net': (5, 84),
'x2.vindicosuite.com': (6, 37),
'rp.gwallet.com': (7, 88)}]
Is there a smart way to filter dictionary d by value so that I have only those positions, where frequency is less than 100? For example:
d=[{'fpdownload2.macromedia.com': (1, 88),
'laposte.net': (2, 23),
'match.rtbidder.net': (5, 84),
'x2.vindicosuite.com': (6, 37),
'rp.gwallet.com': (7, 88)}]
I don't want to use loops, just looking for smart and efficient solution...
You can use a dictionary comprehension with unpacking for a more Pythonic result:
d=[{'fpdownload2.macromedia.com': (1, 88),
'laposte.net': (2, 23),
'www.laposte.net': (3, 119),
'www.google.com': (4, 5441),
'match.rtbidder.net': (5, 84),
'x2.vindicosuite.com': (6, 37),
'rp.gwallet.com': (7, 88)}]
new_data = [{a:(b, c) for a, (b, c) in d[0].items() if c < 100}]
Output:
[{'laposte.net': (2, 23), 'fpdownload2.macromedia.com': (1, 88), 'match.rtbidder.net': (5, 84), 'x2.vindicosuite.com': (6, 37), 'rp.gwallet.com': (7, 88)}]
You can use a dictionary comprehension to do the filtering:
d = {
'fpdownload2.macromedia.com': (1, 88),
'laposte.net': (2, 23),
'www.laposte.net': (3, 119),
'www.google.com': (4, 5441),
'match.rtbidder.net': (5, 84),
'x2.vindicosuite.com': (6, 37),
'rp.gwallet.com': (7, 88),
}
d_filtered = {
k: v
for k, v in d.items()
if v[1] < 100
}
What you want is a dictionary comprehension. I'll show it with a different example:
d = {'spam': 120, 'eggs': 20, 'ham': 37, 'cheese': 101}
d = {key: value for key, value in d.items() if value >= 100}
If you don't already understand list comprehensions, this probably looks like magic that you won't be able to maintain and debug, so I'll show you how to break it out into an explicit loop statement that you should be able to understand easily:
new_d = {}
for key, value in d.items():
if value >= 100:
new_d[key] = value
If you can't figure out how to turn that back into the comprehension, just use the statement version until you learn a bit more; it's a bit more verbose, but better to have code you can think through in your head.
Your problem is slightly more complicated, because the values aren't just a number but a tuple of two numbers (so you want to filter on value[1], not value). And because you have a list of one dict rather than just a dict (so you may need to do this for each dict in the list). And of course my filter test isn't the same as yours. But hopefully you can figure it out from here.
So, I got my list of tuples to sort out by order of ints. What I'm missing is making the sort stable..
How can i make bubble sort stable? (keep order on similar items)
def bubble_sort_2nd_value(tuples_list):
NEWLIST = []
ITEM_MOVE = 0
for i in tuples_list:
NEWLIST.append(i)
for i in range(len(NEWLIST)):
for j in range(i+1, len(NEWLIST)):
if(NEWLIST[j][1] < NEWLIST[i][1]):
ITEM_MOVE = 1
NEWLIST[j],NEWLIST[i] = NEWLIST[i],NEWLIST[j]
if (ITEM_MOVE == 0):
print(tuples_list)
else:
print(NEWLIST)
tuples_list = [('h2', 8), ('h4', 30), ('h6', 7), ('h8', 54), ('h1', 72), ('h3', 8), ('h5', 7), ('h7', 15), ('h7', 24)]
bubble_sort_2nd_value(tuples_list)
tester resault which is expected and y resault comparison :
Showing output from element 0
expected: [('h6', 7), ('h5', 7), ('h2', 8), ('h3', 8), ('h7', 15), ('h9', 24), ('h4', 30), ('h8', 54), ('h1', 72)]
actual: [('h6', 7), ('h5', 7), ('h3', 8), ('h2', 8), ('h7', 15), ('h9', 24), ('h4', 30), ('h8', 54), ('h1', 72)]
result_code bubble_14 wrong 1
notice the h2/3 mix... need to fix it.. that what i mean by not stable
The best thing you could do right now is to understand why it is switching those items. Print at every step what items are being changed. Then you might understand the behaviour.
So I had a go at it, you don't compare the current item with the next item in the list, you compare the current item with all the following items in the list. The changes I made bellow might give you the result you want.
def bubble_sort_2nd_value(tuples_list):
NEWLIST = []
ITEM_MOVE = 0
for i in tuples_list:
NEWLIST.append(i)
for i in range(len(NEWLIST)):
for j in range(len(NEWLIST)-1):
k=j+1
if(NEWLIST[j][1] > NEWLIST[k][1]):
ITEM_MOVE = 1
NEWLIST[j],NEWLIST[k] = NEWLIST[k],NEWLIST[j]
if (ITEM_MOVE == 0):
print(tuples_list)
else:
print(NEWLIST)
tuples_list = [('h2', 8), ('h4', 30), ('h6', 7), ('h8', 54), ('h1', 72), ('h3', 8), ('h5', 7), ('h7', 15), ('h7', 24)]
bubble_sort_2nd_value(tuples_list)
So what you are doing is not 100% bubble sort. Try this and tell me if you need me to explain why yours is not working.
I need to generate a list from the list of tuples:
a = [(1,2), (1,3), (2,3), (2,5), (2,6), (3,4), (3,6), (4,7), (5 6), (5,9), (5,10), (6,7)
(6.10) (6.11) (7.8) (7.12) (8.12) (9.10) (10.11)]
The rule is:
- I have a record from any (begin = random.choice (a))
- Items from the new list must have the following relationship:
the last item of each tuple in the list must be equal to the first item of the next tuple to be inserted.
Example of a valid output (starting by the tuple (3.1)):
[(3, 1), (1, 2), (2, 3), (3, 4), (4, 7), (7, 8), (8, 12), (12, 7), (7, 6), (6, 2), (2, 5), (5, 6), (6, 10), (10, 5) (5, 9), (9, 10), (10, 11), (11, 6), (6, 3)]
How can I do this? Its make using list comprehensions?
Thanks!
Here, lisb will be populated with tuples in the order that you seek. This is, of course, if lisa provides appropriate tuples (ie, each tuple has a 1th value matching another tuple's 0th value). Your sample list will not work, regardless of the implementation, because all the values don't match up (for example, there is no 0th element with 12, so that tuple can't be connected forward to any other tuple)...so you should come up with a better sample list.
Tested, working.
import random
lisa = [(1, 2), (3, 4), (2, 3), (4, 0), (0, 9), (9, 1)]
lisb = []
current = random.choice(lisa)
while True:
lisa.remove(current)
lisb.append(current)
current = next((y for y in lisa if y[0] == current[1]), None)
if current == None:
break
print lisb
If you don't want to delete items from lisa, just slice a new list.
As a generator function:
def chained_tuples(x):
oldlist = x[::]
item = random.choice(oldlist)
oldlist.remove(item)
yield item
while oldlist:
item = next(next_item for next_item in oldlist if next_item[0] == item[1])
oldlist.remove(item)
yield item
As noted, you'll get an incomplete response if your list isn't actually chainable all the way through, like your example list.
Just to add another way of solving this problem:
import random
from collections import defaultdict
lisa = [(1, 2), (3, 4), (2, 3), (4, 0), (0, 9), (9, 1)]
current_start, current_end = lisa[random.randint(0, len(lisa) - 1)]
starts = defaultdict(list)
lisb = [(current_start, current_end)]
for start, end in lisa:
starts[start].append(end)
while True:
if not starts[current_end]:
break
current_start, current_end = current_end, starts[current_end].pop()
lisb.append((current_start, current_end))
Note: You have to make sure lisa is not empty.
I think all of the answers so far are missing the requirement (at least based on your example output) that the longest chain be found.
My suggested solution is to recursively parse all possible chains that can be constructed, and return the longest result. The function looks like this:
def generateTuples(list, offset, value = None):
if value == None: value = list[offset]
list = list[:offset]+list[offset+1:]
res = []
for i,(a,b) in enumerate(list):
if value[1] in (a,b):
if value[1] == a:
subres = generateTuples(list, i, (a,b))
else:
subres = generateTuples(list, i, (b,a))
if len(subres) > len(res):
res = subres
return [value] + res
And you would call it like this:
results = generateTuples(a, 1, (3,1))
Producing the list:
[(3, 1), (1, 2), (2, 3), (3, 4), (4, 7), (7, 8), (8, 12), (12, 7), (7, 6),
(6, 2), (2, 5), (5, 6), (6, 10), (10, 5), (5, 9), (9, 10), (10, 11),
(11, 6), (6, 3)]
The first parameter of the function is the source list of tuples, the second parameter is the offset of the first element to use, the third parameter is optional, but allows you to override the value of the first element. The latter is useful when you want to start with a tuple in its reversed order as you have done in your example.
I'm working on some python dicts of tuples. Each tuple containing 2 ints. The first digit in the tuple is reffered to as value and the second digit is referred to as work. I have 3 different comparators and I need to sort the dicts into descending order. This order should be determined by which comparator is called. i.e. the dict can be sorted 3 different ways. I've tried as many different ways as I could find to get this to work. I can do it without using the comparator by just breaking it up into a list and sorting by slicing the tuples but if anyone can shed some light on the syntax to sort using the comparators it would be greatly appreciated. Mine seems to be returning correctly for cmpWork but the other 2 aren't reversed.
Also it would be great if I could get the dict sorted by the tuple values.
I got a sort working with
sortedSubjects = sorted(tmpSubjects.iteritems(), key = operator.itemgetter(1), reverse = True)
but this doesn't let me slice the tuples.
First time posting noob so apologies for any mistakes.
def cmpValue(subInfo1, subInfo2):
return cmp(subInfo2[0] , subInfo1[0])
def cmpWork(subInfo1, subInfo2):
return cmp(subInfo1[1] , subInfo2[1])
def cmpRatio(subInfo1, subInfo2):
return cmp((float(subInfo2[0]) / subInfo2[1]) , (float(subInfo1[0]) / subInfo1[1]))
def greedyAdvisor(subjects, comparator):
tmpSubjects = subjects.copy()
sortedSubjects = sorted(tmpSubjects.values(), comparator, reverse = True)
print sortedSubjects
smallCatalog = {'6.00': (16, 8),'1.00': (7, 7),'6.01': (5, 3),'15.01': (9, 6)}
greedyAdvisor(smallCatalog, cmpRatio)
greedyAdvisor(smallCatalog, cmpValue)
greedyAdvisor(smallCatalog, cmpWork)
[(7, 7), (9, 6), (5, 3), (16, 8)]
[(5, 3), (7, 7), (9, 6), (16, 8)]
[(16, 8), (7, 7), (9, 6), (5, 3)]
ps
The line
sortedSubjects = sorted(tmpSubjects.iteritems(), key = operator.itemgetter(1), reverse = True)
returns
[('6.00', (16, 8)), ('15.01', (9, 6)), ('1.00', (7, 7)), ('6.01', (5, 3))]
which is almost exactly what I'm looking for except that I can't sort by the second value in the tuple and I can't sort by cmpRatio either.
but this doesn't let me slice the tuples
Starting with your example:
sortedSubjects = sorted(tmpSubjects.iteritems(),
key=operator.itemgetter(1),
cmp=comparator, # What about specifying the comparison?
reverse=True)
If you need to sort dictionary - use collections.OrderedDict
E.g., sort by 1st element of tuple
OrderedDict(sorted(smallCatalog.items(), key=lambda e:e[1][0]))
Out[109]: OrderedDict([('6.01', (5, 3)), ('1.00', (7, 7)), ('15.01', (9, 6)), ('6.00', (16, 8))])