Home > Software engineering >  reverse sorting gone wrong in python
reverse sorting gone wrong in python

Time:01-18

I am trying to create a script, that will get a tuple, sort it by value AND by name- for example if I have:

(('apple', 5), ('tv', 500), ('bee', 1000), ('cat', 500))

I want it to return:

['bee', 'cat', 'tv', 'apple']

so that the item with the biggest number will be first, but if two items have the same value the one that is lexicographically smaller will appear first. this is my code:

def find_k_most_expensive_products(data, k):
    executed_file = executeMtmikya(data)
    sorted_prices_tup = sorted(executed_file[2], reverse=True, key=lambda element: 
                              (executed_file[2][1], executed_file[2][0]))
    best_sellers = []

    print("------------")
    print("this is the sorted prices_tup: ")
    print(sorted_prices_tup)
    print("------------")
    for i in sorted_prices_tup:
        while k > 0:
            best_sellers.append(i[1])
            print("k is- ")
            print(k)
            break
        k -= 1
    return best_sellers

But this is what I get instead, given:

{'apple': '5', 'tv': '500', 'bee': '1000'}

------------
this is the sorted prices_tup: 
[('5', 'apple'), ('500', 'tv'), ('1000', 'bee')]
------------
k is- 
3
k is- 
2
k is- 
1
['apple', 'tv', 'bee']

Why isn't it working as expected?

CodePudding user response:

As you got a hint, you need to use the key parameter ofsorted. You however did not do it correctly as your lambda does not use the object that is passed as parameter.

One option is to take the opposite of the number as first key for reverse sorting, and the word as second key for lexicographic sorting:

t = (('apple', 5), ('tv', 500), ('bee', 1000), ('cat', 500))

[x for x,_ in sorted(t, key=lambda x: (-x[1], x[0]))]

Output: ['bee', 'cat', 'tv', 'apple']

CodePudding user response:

Here is an alternate approach if you did not know you can sort on more than one key. I sort by the numbers first, then I sort by the word in a while loop:

I need the backtrack method to ensure that all the switches occur. Sorry for my verbosity.

def backtrack(i, result):
    while i>0:
        #print("In backtrack: ", result[i][0],result[i 1][0])
        if i-1 > 0 and result[i-1][1] == result[i][1] and result[i-1][0]>result[i][0]:
            result[i-1], result[i] = result[i],result[i-1]
            i-=1
        else:
            i-=1


initial = (('apple', 5), ('tv', 500), ('bee', 1000), ('cat', 500))

initial = sorted(initial, key = lambda element: element[1], reverse=True)

result = list(initial)
i=0
while i< len(result)-1:
    if  result[i][1] == result[i 1][1] and result[i][0]>result[i 1][0]:
        result[i], result[i 1] = result[i 1],result[i]
        backtrack(i, result)
        i =1
    else:
        i =1

final = [x[0] for x in result]
print(final)

Output:

['bee', 'cat', 'tv', 'apple']

CodePudding user response:

try sorted:

def sort_by_second(arr):
    return sorted(arr, key=lambda x: (-1*x[1],x[0]),reverse=False)

arr = [('apple', 5), ('tv', 500), ('bee', 1000), ('cat', 500)]

print(list(map(lambda x:x[0],sort_by_second(arr))))

output:

[bee', 'cat', 'tv', 'apple']
  •  Tags:  
  • Related