Ranking a list of tuples with same values? - python-3.x

I want to rank this list of tuples:
[("Blueberries", 1), ("Strawberries", 2), ("Apple", 3), ("Apple", 4), ("Orange", 2)]
It should output:
[("Apple", 4), ("Apple", 3), ("Strawberries", 2), ("Orange", 2), ("Blueberries", 1)]
A dictionary works great without duplicate values. Is there any other way I could approach this? Or is there a way I could do this with a dictionary? I'm completely lost.

You can sort a list using the key= parameter to define which function you want to use for the sort. In this case, it looks like you want to sort based off of the second item in the tuple, so:
l = [("Blueberries", 1), ("Strawberries", 2), ("Apple", 3), ("Apple", 4), ("Orange", 2)]
sorted_list = sorted(l,key=lambda x: x[1], reverse=True)
You can do this without using a lambda function by just defining that function with a name.
def my_sort_func(item):
return item[1]
sorted_list = sorted(l, key=my_sort_func, reverse=True)

Related

Condense list of nested tuples

I have an assignment that I have successfully solved using defaultdict(list).
In a nutshell, take two pairs of points (Ax, Ay) and (Bx, By) and compute the slope.
Then combine all points that have the same slope together.
Using defaultdict(list) I did this:
dic = defaultdict(list)
for elem in result:
x1 = elem[0][0]
y1 = elem[0][1]
x2 = elem[1][0]
y2 = elem[1][1]
si = slope_intercept(x1, y1, x2, y2)
temp = defaultdict(list)
temp[si].append(elem)
FullMergeDict(dic, temp)
temp.clear()
Works perfectly. (Yes, there's a lot more to the whole program not shown.)
However, I am being told to discard defaultdict(list) and that I must use a nested tuple based structure.
I have a list of tuples where the structure looks like: (((1, 2), 3), (2, 5))
(1, 2) is the first coordinate point
3 is the computed slope
(2, 5) is the second coordinate point
NOTE: These are just made up values to illustrate structure. The points almost certainly will not
generate the shown slopes.
If I start with this:
start = [(((1, 2), 3), (2, 5)), (((4, 5), 2), (3, 7)), (((2, 4), 1), (8, 9)), (((1, 2), 3), (4, 8))]
I need to end up with this:
end = [((1, 2), (2, 5), (1, 2), (4, 8)), ((4, 5), (3, 7)), ((2, 4), (8, 9))]
For every unique slope, I need a tuple of all the coordinates that share that same slope.
In the above example, the first and last tuples shared the same slope, 3, so all pairs of coordinates
with slope 3 are combined into one tuple. Yes I realize that (1, 2) is represented twice in my example. If there was another set of coordinates with slope 3, then the first tuple would contain
those additional coordinates, including duplicates. Note the embedded slope from 'start' is discarded.
defaultdict(list) made this quite straightforward. I made the key the slope and then merged the values (coordinates).
I can't seem to work through how to transform 'start' into 'end' using this required structure.
I'm not sure what you mean by "I must use the structure detailed above". You have start, you want end, so at some point there is a change to the structure. Do you mean that you are not allowed to use a dictionary or a list at all? How does your instructor expect that you go from start to end without using anything else? Here's an approach that uses only tuples (and the start and end lists).
end will be a list of tuples. We'll keep track of the slope in the a separate list. Expect end and lookup to look like so:
lookup = [ slope_1, , slope_2, ...]
end = [((p1_x, p1_y), (p2_x, p2_y), ...), ((p10_x, p10_y), (p11_x, p11_y)), ...]
start = [(((1, 2), 3), (2, 5)), (((4, 5), 2), (3, 7)), (((2, 4), 1), (8, 9)), (((1, 2), 3), (4, 8))]
end = []
lookup = []
def find_tuple_index_with_slope(needle_slope):
for index, item in enumerate(lookup):
if item == needle_slope:
return index
return None
for item in start:
p1 = item[0][0]
slope = item[0][1]
p2 = item[1]
# Check if end already contains this slope
slope_index = find_tuple_index_with_slope(slope)
if slope_index is None:
# If it doesn't exist, add an item to end
end.append(p1, p2))
# And add the slope to lookup
lookup.append(slope)
else:
# If it exists, append the new points to the existing value and
# reassign it to the correct index of end
end[slope_index] = (*end[slope_index], p1, p2)
Now, we have end looking like so:
[((1, 2), (2, 5), (1, 2), (4, 8)), ((4, 5), (3, 7)), ((2, 4), (8, 9))]
The reason this approach isn't great is the function find_tuple_index_with_slope() needs to iterate over all the elements in end to look up the correct one to append to. This increases the time complexity of the code, when you could use a dictionary to do this lookup and it would be much faster, especially if you have lots of points and lots of distinct values of slope.
A better way: replace the lookup function with a new dictionary, where the keys are the values of slope, and the values are the indices in end where the corresponding tuple is stored.
lookup = dict()
end = []
for item in start:
p1 = item[0][0]
slope = item[0][1]
p2 = item[1]
# Find the index of the tuple for `slope` using the lookup
slope_index = lookup.get(slope, None)
if slope_index is None:
# If it doesn't exist, add an item to end
end.append((p1, p2))
# And add that index to lookup
lookup[slope] = len(end) - 1
else:
end[slope_index] = (*end[slope_index], p1, p2)
The code looks almost the same as before, but looking up using a dictionary instead of a list is what saves you time.

I have an issue in Python Lists,how to solve it?

I want a code in Python lists,to get all the possibility in a given list without using any built in functions.
example = [1,2,3]
def expandList(ex):
rslt = []
for i in range(len(ex)):
for j in range(len(ex)):
rslt.append((ex[i], ex[j]))
return rslt
expandList(example)
Yields:
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
If you are going for each permutation, you would use nested for loops. Example:
permutations = list()
for item in myList:
for item2 in myList:
permutations.append((item, item2))
This code will create a list of permutations.

How to sort and remove tuples with same first element and only keeping the first occurrence

Support we have a list of tuples listeT:
ListeT=[('a', 1), ('x',1) , ('b', 1), ('b', 1), ('a', 2), ('a',3), ('c', 6), ('c', 5),('e', 6), ('d', 7),('b', 2)]` and i want to get the following result:
Result = [('a', 1), ('x',1) , ('b', 1), ('c', 5), ('c', 6), ('e', 6), ('d', 7)]`
1-I want to order this list according to the second element of tuples.
2- I want to remove duplicates and only keep the first occurrence of tuples having the same value of first elements: For instance if have ('a', 1) and (a,2), I want to keep only ('a', 1).
For the sorting I used : res=sorted(listT, key=lambda x: x[1], reverse= True) and it worked.
But for the duplicates I could't find a good solution:
I can remove duplicate elements by converting the the list to a set (set(listeT)) or by using
numpy.unique(ListeT, axis=0). However, this only removes the duplicates for all the tuples but I want also to remove the duplicates of tuples having the same first element and only keeping the first occurrence.
Thank you.
The dict can take care of the uniqueness while feeding it in reversed order.
I did not understood if you need the outer sort so you can just replace it with list() if not needed.
sorted(dict(sorted(ListeT, key=lambda x: x[1], reverse= True)).items(), key=lambda x: x[1])
[('a', 1), ('b', 1), ('x', 1), ('c', 5), ('e', 6), ('d', 7)]

How to compare the first tuple from one list of tuples with the first from another list, then the second with the second list, and so on?

I'm trying to compare two lists of tuples made of integers and I cannot seem to succeed.
list_a = [(1, 1), (2, 2), (3, 4), (4, 1)]
list_b = [(1, 2), (2, 2), (3, 1), (4, 1)]
I'm trying to compare the first tuple with the first tuple of the other list, then the second with the second, then the third and so on.
I tried to loop through the two lists and values, like below.
for w, x in list_a:
for y, z in list_b:
if x == z:
total += 1
break
else:
total -= 1
break
In the first loop, the variables "w" and "x" from value will get the values: (1, 1). Then "y" and "z" will get (1, 2) and will compare. So far so good.
My problem is that then "y" and "z" will loop through the second tuple of list_b, whilst "w" and "x" will remain with the first tuple of list_a
I hope this is understandable, I'm sorry, I have good english knowledge but sometimes it's a little hard to explain this kind of stuff.
You should zip() them together so you can compare the values of the entire tuple in one list iterate:
list_a = [(1, 1), (2, 2), (3, 4), (4, 1)]
list_b = [(1, 2), (2, 2), (3, 1), (4, 1)]
total = 0
for (w, x), (y, z) in zip(list_a, list_b):
# (w, x) are from list_a
# (y, z) are from list_b
if x == z:
total += 1
else:
total -= 1

Check if the product of two consecutive list numbers equals another number

The code prints out 2 and 3 because their product equals the variable num. But what if l=[1,3,4,5,6,7,8,9,10]? No numbers in the list multiplied equal 6,so I'd like to print the two closest ones.
l=[1,2,3,4,5,6,7,8,9,10]
num=6
index=0
while index+1<len(l):
if l[index]*l[index+1]==num:
print(l[index],l[index+1])
index+=1
You can do this with an easy expression with min:
First we use zip to build an iterator for consecutive elements: zip(l, l[1:])
Then we use min with the key being the distance from num:
min(zip(l, l[1:]), key = lambda x: abs(x[0]*x[1]-num))
If l = [1,2,3,4,5,6,7,8,9,10]
Output:
(2, 3)
If l = [1,3,4,5,6,7,8,9,10]
Output:
(1, 3)
If you want to get more outputs consider using sorted in the same manner to get a ranking:
sorted(zip(l, l[1:]), key = lambda x: abs(x[0]*x[1]-num))
If l = [1,3,4,5,6,7,8,9,10]
Output:
[(1, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10)]
If l = [1,2,3,4,5,6,7,8,9,10]
Output:
[(2, 3), (1, 2), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10)]
To find the index for the pair whose product is closest to num you can do:
Code:
min((abs(x*y - num), i) for i, (x, y) in enumerate(zip(l, l[1:])))[1]
Say what?
This uses a generator expression and min() to find the pair whose product is closest to num. In that chain is:
zip(l, l[1:])
which produces a tuple for each neighbor pair. Then enumerate is used to also produce the index. Then the absolute value of the product - num is passed to min()

Resources