1

I have a list of lists and I want to learn how to sort the list by the element at index 1 but also sorted by the element at index 2 if index 1 returns the same number for two items.

I want to do this without the use of inbuilt functions and methods so that I can continue to develop my understanding of lists and how to manipulate them.

To recap:

  • I have a list of lists
  • Each sublist has the same number of elements
  • I am trying to sort them in descending order by creating a new unsorted list which is a copy of the original list (I don't want to modify the original unsorted list) and looping over the copy of the unsorted list to grab the highest number in (from index 1) and then appending that to a newly created sorted_lists variable
  • I then remove that list from the original unsorted list
  • I repeat the process until one by one the remaining lists with the highest value is added to the new sorted list and removed from the original list

I have tried a few different things but cannot get it to work. Any help would be appreciated.

# initialising list
food_list = (
    ["banana", 10, "f", "yellow"],
    ["apple", 12, "f", "red"],
    ["pear", 60, "f", "green"],
    ["mango", 5, "f", "yellow"],
    ["lettuce", 3, "v", "green"],
    ["beans", 20, "v", "green"],
    ["red capsicum", 1, "v", "red"],
    ["corn", 20, "v", "yellow"],
)

unsorted_food_list_copy = food_list
sorted_food_list = []

while len(unsorted_food_list_copy) != 0:
    maximum = 0
    for food in unsorted_food_list_copy:
        if food[1] > maximum:
            maximum = food[1]
    sorted_food_list.append(maximum)
    unsorted_food_list_copy.remove(maximum)

I have also tried this:

# initialising list
food_list = (
    ["banana", 10, "f", "yellow"],
    ["apple", 12, "f", "red"],
    ["pear", 60, "f", "green"],
    ["mango", 5, "f", "yellow"],
    ["lettuce", 3, "v", "green"],
    ["beans", 20, "v", "green"],
    ["red capsicum", 1, "v", "red"],
    ["corn", 20, "v", "yellow"],
)

unsorted_food_list_copy = food_list
sorted_food_list = []

while unsorted_food_list_copy:
    min = unsorted_food_list_copy[1]
    for x in unsorted_food_list_copy:
        if x < min:
            min = x
    sorted_food_list.append(min)
    unsorted_food_list_copy.remove(min)
Laurent LAPORTE
  • 21,958
  • 6
  • 58
  • 103
K-J
  • 99
  • 9
  • `unsorted_food_list_copy = food_list` does not make a copy. To find out why check out: [List changes unexpectedly after assignment. Why is this and how can I prevent it?](https://stackoverflow.com/questions/2612802/list-changes-unexpectedly-after-assignment-why-is-this-and-how-can-i-prevent-it). – DarrylG Mar 08 '22 at 12:09
  • 1
    Don't use popular built-in function names as variable names (i.e. min). Suggest min_. – DarrylG Mar 08 '22 at 12:10
  • you have two items in your list which have equal values for both index 1 and index 2, what is the logic there for a tiebreaker – gold_cy Mar 08 '22 at 12:11
  • 1
    food_list is a tuple of lists - not a list of lists – DarkKnight Mar 08 '22 at 12:17

3 Answers3

2

In your code sample, you define food_list as a tuple while mentioning a list of list. In order to use list function like remove, copy or append, you need to add brackets around your lists.

Firstly, your food_list should be defined this way :

food_list = [
    ['banana', 10, 'f', 'yellow'],
    ['apple', 12, 'f', 'red'],
    ['pear', 60, 'f', 'green'],
    ['mango', 5, 'f', 'yellow'],
    ['lettuce', 3, 'v', 'green'],
    ['beans', 20, 'v', 'green'],
    ['red capsicum', 1, 'v', 'red'],
    ['corn', 20, 'v', 'yellow'],
]

Secondly you set up your minimum value before iterating over the list, you consider the 1st element of your list in order to start looking for a lower integer.

minValue = unsorted_food_list_copy[0]

Complete solution :

# initializing list
food_list = [
    ['banana', 10, 'f', 'yellow'],
    ['apple', 12, 'f', 'red'],
    ['pear', 60, 'f', 'green'],
    ['mango', 5, 'f', 'yellow'],
    ['lettuce', 3, 'v', 'green'],
    ['beans', 20, 'v', 'green'],
    ['red capsicum', 1, 'v', 'red'],
    ['corn', 20, 'v', 'yellow'],
]

unsorted_food_list_copy = food_list.copy()
sorted_food_list = []

for i in range(len(unsorted_food_list_copy)):
    minValue = unsorted_food_list_copy[0]
    for x in unsorted_food_list_copy:
        if x[1] < minValue[1]:
            minValue = x
    sorted_food_list.append(minValue)
    unsorted_food_list_copy.remove(minValue)

sorted_food_list_descending = sorted_food_list[::-1]
print(sorted_food_list_descending)

# Ouput
    [['pear', 60, 'f', 'green'],
    ['corn', 20, 'v', 'yellow'],
    ['beans', 20, 'v', 'green'],
    ['apple', 12, 'f', 'red'],
    ['banana', 10, 'f', 'yellow'],
    ['mango', 5, 'f', 'yellow'],
    ['lettuce', 3, 'v', 'green'],
    ['red capsicum', 1, 'v', 'red']]
Titouan L
  • 1,182
  • 1
  • 8
  • 24
  • Note: poster requested descending order. – DarrylG Mar 08 '22 at 12:34
  • You are right @DarrylG, thanks for pointing that out. I added a line to reverse the list (without using built-in `reverse()` function) – Titouan L Mar 08 '22 at 12:43
  • 1
    Thank you Titouan for your detailed help. I had no idea (obviously) that I wasn't making a copy - so thank you for pointing out that mistake too! I did need it in descending order but I realise I confused things by using min as variable names. Based on what you helped with, I was able to figure out how to modify the code to get it to sort in descending order :) Appreciate your help :) – K-J Mar 08 '22 at 12:45
1

To do this in descending order you could do this:

food_list = [
    ['banana', 10, 'f', 'yellow'],
    ['apple', 12, 'f', 'red'],
    ['pear', 60, 'f', 'green'],
    ['mango', 5, 'f', 'yellow'],
    ['lettuce', 3, 'v', 'green'],
    ['beans', 20, 'v', 'green'],
    ['red capsicum', 1, 'v', 'red'],
    ['corn', 20, 'w', 'yellow'],
]
food_list_copy = food_list.copy()
new_list = []

while food_list_copy:
    hi = food_list_copy[0]
    pi = 0
    for i, e in enumerate(food_list_copy[1:], 1):
        if e[1] > hi[1]:
            hi = e
            pi = i
        elif e[1] == hi[1]:
            if e[2] > hi[2]:
                hi = e
                pi = i
    new_list.append(hi)
    food_list_copy.pop(pi)
print(new_list)

Output:

[['pear', 60, 'f', 'green'],
 ['corn', 20, 'w', 'yellow'],
 ['beans', 20, 'v', 'green'],
 ['apple', 12, 'f', 'red'],
 ['banana', 10, 'f', 'yellow'],
 ['mango', 5, 'f', 'yellow'],
 ['lettuce', 3, 'v', 'green'],
 ['red capsicum', 1, 'v', 'red']]
Laurent LAPORTE
  • 21,958
  • 6
  • 58
  • 103
DarkKnight
  • 19,739
  • 3
  • 6
  • 22
0

The pythonic way to sort a list according to a specify (user-defined) key is to use sort with the key parameter.

food_list = [
    ["banana", 10, "f", "yellow"],
    ["apple", 12, "f", "red"],
    ["pear", 60, "f", "green"],
    ["mango", 5, "f", "yellow"],
    ["lettuce", 3, "v", "green"],
    ["beans", 20, "v", "green"],
    ["red capsicum", 1, "v", "red"],
    ["corn", 20, "w", "yellow"],
]

# create a copy (you can also use `copy.deepcopy`) and sort
sorted_food_list = [list(i) for i in food_list]
sorted_food_list.sort(key=lambda i: (-i[1], i[2]))

output

[['pear', 60, 'f', 'green'],
 ['beans', 20, 'v', 'green'],
 ['corn', 20, 'w', 'yellow'],
 ['apple', 12, 'f', 'red'],
 ['banana', 10, 'f', 'yellow'],
 ['mango', 5, 'f', 'yellow'],
 ['lettuce', 3, 'v', 'green'],
 ['red capsicum', 1, 'v', 'red']]
Laurent LAPORTE
  • 21,958
  • 6
  • 58
  • 103