# Lists / Sorting a List

**URL:** <https://discuss.python.org/t/lists-sorting-a-list/16144>\
**Category:** Python Help\
**Tags:** help\
**Created:** [June 1, 2022, 12:35am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144 "2022-06-01T00:35:13Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![malik](https://avatars.discourse-cdn.com/v4/letter/m/e36b37/32.png) [@malik](https://discuss.python.org/u/malik)\
**Post date:** [June 1, 2022, 12:35am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/1 "2022-06-01T00:35:13Z")

</div>

Hi!

I have a sample list with 11 objects.  
I want to get:

1. Sorted list by LIKES
2. Most popular actions (ex. LIKE, or SAVE, etc).

Pleas help me.

```auto
from typing import List

logs: List = [
    ['30-MAY', 'user1', 'LIKE'],
    ['29-MAY', 'user20', 'COMMENT'],
    ['31-MAY', 'user11', 'COMMENT'],
    ['25-MAY', 'user145', 'LIKE'],
    ['27-MAY', 'user16', 'COMMENT'],
    ['28-MAY', 'user5', 'COMMENT'],
    ['31-MAY', 'user3', 'LIKE'],
    ['1-JUNE', 'user8', 'SAVE'],
    ['23-MAY', 'user90', 'LIKE'],
    ['1-JUNE', 'user12', 'LIKE'],
    ['1-JUNE', 'user89', 'SAVE'],
]

```

---

<div class="post-metadata">

**Author:** ![mlgtechuser](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mlgtechuser/32/7310_2.png) [@mlgtechuser](https://discuss.python.org/u/mlgtechuser)\
**Post date:** [June 1, 2022, 3:12am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/2 "2022-06-01T03:12:38Z")

</div>

Hi Malik. Do you need to _ **sort** _ or only _ **filter** _?

If sorting, what list position(s) is the sort index?  
(And if you need more than one sort index, which is 1st, 2nd, etc.?)

---

<div class="post-metadata">

**Author:** ![vbrozik](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/vbrozik/32/7423_2.png) [@vbrozik](https://discuss.python.org/u/vbrozik)\
**Post date:** [June 1, 2022, 8:01am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/3 "2022-06-01T08:01:21Z")

</div>

> [@malik](#):
>
> 1. Sorted list by LIKES
> 2. Most popular actions (ex. LIKE, or SAVE, etc).

It is really unclear what you mean in 1.

For the second task a Pythonic implementation can look like:

```auto
import collections

log_action_counts = collections.Counter(log_event[2] for log_event in logs)
log_action_counts_sorted = log_action_counts.most_common()

```

The first command counts the number of occurrence of individual actions.  
The second command sorts the counts so that the most numerous actions are first in the resulting list.

Old implementation of the second command before I noticed `collections.Counter.most_common()` 🙂

```auto
import operator

log_action_counts_sorted = sorted(
        log_action_counts.items(), key=operator.itemgetter(1), reverse=True)

```

---

<div class="post-metadata">

**Author:** ![malik](https://avatars.discourse-cdn.com/v4/letter/m/e36b37/32.png) [@malik](https://discuss.python.org/u/malik)\
**Post date:** [June 2, 2022, 12:54am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/4 "2022-06-02T00:54:34Z")

</div>

Hello! Thank you for your response!  
I will just give you what I want as a response.

1. Imagine we have thousands of rows. and I want the `logs` variable to start with `LIKE` actions first. Like i showed in the example.

```auto
logs: List = [
    ['30-MAY', 'user1', 'LIKE'],
    ['25-MAY', 'user145', 'LIKE'],
    ['31-MAY', 'user3', 'LIKE'],
    ['23-MAY', 'user90', 'LIKE'],
    ['1-JUNE', 'user12', 'LIKE'],
    ['29-MAY', 'user20', 'COMMENT'],
    ['31-MAY', 'user11', 'COMMENT'],
    ['27-MAY', 'user16', 'COMMENT'],
    ['28-MAY', 'user5', 'COMMENT'],
    ['1-JUNE', 'user8', 'SAVE'],
    ['1-JUNE', 'user89', 'SAVE'],
]

```

1. Again, imagine we have a lot of data here, and I want to see the most popular action. Please have a look at the example below. So we have 5 `LIKE` actions, then 4 `COMMENT` and 2 `SAVE`.

```auto
logs: List = [
    ['30-MAY', 'user1', 'LIKE'],
    ['25-MAY', 'user145', 'LIKE'],
    ['31-MAY', 'user3', 'LIKE'],
    ['23-MAY', 'user90', 'LIKE'],
    ['1-JUNE', 'user12', 'LIKE'],
    ['29-MAY', 'user20', 'COMMENT'],
    ['31-MAY', 'user11', 'COMMENT'],
    ['27-MAY', 'user16', 'COMMENT'],
    ['28-MAY', 'user5', 'COMMENT'],
    ['1-JUNE', 'user8', 'SAVE'],
    ['1-JUNE', 'user89', 'SAVE'],
]

```

Hope it makes more sense now, if not, please leave a comment and I will reply.

---

<div class="post-metadata">

**Author:** ![malik](https://avatars.discourse-cdn.com/v4/letter/m/e36b37/32.png) [@malik](https://discuss.python.org/u/malik)\
**Post date:** [June 2, 2022, 12:55am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/5 "2022-06-02T00:55:35Z")

</div>

Hello!  
Here I explained more: [Lists / Sorting a List - #4 by malik](https://discuss.python.org/t/lists-sorting-a-list/16144/4)

---

<div class="post-metadata">

**Author:** ![mlgtechuser](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mlgtechuser/32/7310_2.png) [@mlgtechuser](https://discuss.python.org/u/mlgtechuser)\
**Post date:** [June 2, 2022, 4:38am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/6 "2022-06-02T04:38:53Z")

</div>

So, you would like to sort the parent logList items by most popular. Is “most popular” defined by how many times an action type was logged? …Or is “most popular” a static sort order of the `'LIKE' / 'COMMENT' / 'SAVE'` values?

Assuming the sort order is static (because we can add dynamic sort order later) my first thought is to…

1. filter out each action type into temporary lists
2. concatenate those three lists together in the order you need.

[Edit:] Your parent logList has an extra comma at the end. The Python interpreter is cleaning this up for you. If the logList is being automatically populated, the extra comma does not cause an error. (Note that the interpreter _ **could** _ be changed in the future so that this extra comma becomes a problem.)

[EDIT:] Here’s a loop to create the filtered lists:

```python
List = [...] # <<< This is your actual 'List' object, obviously,
item = "" # with its values and child list objects.
likeList = []
for item in List:
    if item[2] == 'LIKE':
        print(item[2])
        likeList.append(item)
print(likeList)

```

---

<div class="post-metadata">

**Author:** ![aivarpaalberg](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/aivarpaalberg/32/9457_2.png) [@aivarpaalberg](https://discuss.python.org/u/aivarpaalberg)\
**Post date:** [June 2, 2022, 9:31am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/7 "2022-06-02T09:31:01Z")

</div>

Sorting with priority can be done with taking advantage of key function, closure and how Python sorts tuples:

```python
logs = [['30-MAY', 'user1', 'LIKE'],
        ['29-MAY', 'user20', 'COMMENT'],
        ['31-MAY', 'user11', 'COMMENT'],
        ['25-MAY', 'user145', 'LIKE'],
        ['27-MAY', 'user16', 'COMMENT'],
        ['28-MAY', 'user5', 'COMMENT'],
        ['31-MAY', 'user3', 'LIKE'],
        ['1-JUNE', 'user8', 'SAVE'],
        ['23-MAY', 'user90', 'LIKE'],
        ['1-JUNE', 'user12', 'LIKE'],
        ['1-JUNE', 'user89', 'SAVE'],]

def sort_with_priority(data, priority):
    def helper(record):
        if record[-1] == priority:
            return (0, record)
        return (1, record)
    return sorted(data, key=helper) # or data.sort(key=helper) for inplace sorting

print(*sort_with_priority(logs, 'LIKE'), sep="\n")

['1-JUNE', 'user12', 'LIKE']
['23-MAY', 'user90', 'LIKE']
['25-MAY', 'user145', 'LIKE']
['30-MAY', 'user1', 'LIKE']
['31-MAY', 'user3', 'LIKE']
['1-JUNE', 'user8', 'SAVE']
['1-JUNE', 'user89', 'SAVE']
['27-MAY', 'user16', 'COMMENT']
['28-MAY', 'user5', 'COMMENT']
['29-MAY', 'user20', 'COMMENT']
['31-MAY', 'user11', 'COMMENT']

```

---

<div class="post-metadata">

**Author:** ![steven.daprano](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steven.daprano/32/1083_2.png) [@steven.daprano](https://discuss.python.org/u/steven.daprano)\
**Post date:** [June 2, 2022, 9:40am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/8 "2022-06-02T09:40:27Z")

</div>

You need a key function. Try this to sort LIKE first, COMMENT second and  
SAVE third, with anything else last.

```python
def sort_like_first(item):
    return ({'LIKE': 1, 'COMMENT': 2, 'SAVE': 3}.get(item[2], 9999), item)

List.sort(key=sort_like_first)

```

That is equivalent to the following code, but more efficient and faster:

```python

new_list = []
for item in List:
    rating = item[2]
    if rating == 'LIKE':
        score = 1
    elif rating == 'COMMENT':
        score = 2
    elif rating == 'SAVE':
        score = 3
    else:
        score = 9999
    key = (score, item)
    new_list.append(key)

new_list.sort()

i = 0
for score, item in new_list:
    List[i] = item
    i += 1

```

Warning: I haven’t tested either code snippet, but they should work.

---

<div class="post-metadata">

**Author:** ![steven.daprano](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steven.daprano/32/1083_2.png) [@steven.daprano](https://discuss.python.org/u/steven.daprano)\
**Post date:** [June 2, 2022, 9:42am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/9 "2022-06-02T09:42:39Z")

</div>

Your version groups all the “LIKE” items together, but the “COMMENT” and “SAVE” items will appear mixed together.

---

<div class="post-metadata">

**Author:** ![malik](https://avatars.discourse-cdn.com/v4/letter/m/e36b37/32.png) [@malik](https://discuss.python.org/u/malik)\
**Post date:** [June 2, 2022, 11:14am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/10 "2022-06-02T11:14:34Z")

</div>

Thank you @aivarpaalberg This worked perfectly fine and this is what I was looking for.

---

<div class="post-metadata">

**Author:** ![mlgtechuser](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mlgtechuser/32/7310_2.png) [@mlgtechuser](https://discuss.python.org/u/mlgtechuser)\
**Post date:** [June 4, 2022, 3:35pm UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/11 "2022-06-04T15:35:14Z")

</div>

Malik, here is a very compact version that does not require an external function definition.

```python
sortidx_dict = {'LIKE': 1, 'COMMENT': 2, 'SAVE': 3}
List.sort(key=lambda idx: sortidx_dict.get(idx[2], 9999))

```

This is @steven.daprano’s `def sort_like_first()` function written as an in-line `lambda:` function. I find this to be more pythonic because the code is all in one location and the sort index is separated for ease of updating or manipulating through other code, which satisfies part two of your question:

> [@malik](#):
>
> …see the most popular action…

By adding one more line to import `Counter` from the standard library, you can **dynamically** count the number of actions and sort by them. The following code will count _ **any and all action types** _ in `List`.

```python
from collections import Counter
sortidx_dict = Counter([item[2] for item in List])
List.sort(key=lambda idx: sortidx_dict.get(idx[2]), reverse=True)

```

Pythonic Bonus: Since we’re feeding `.get()` with 100% valid actions, I was able to remove the ‘9999’ index value returned as a “not found” result.

If someone would like to do a speed test of the three List Key methods in this thread, I’d be very interested to know how the `lambda:` compares to the others.

---

<div class="post-metadata">

**Author:** ![mlgtechuser](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mlgtechuser/32/7310_2.png) [@mlgtechuser](https://discuss.python.org/u/mlgtechuser)\
**Post date:** [June 4, 2022, 4:14pm UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/12 "2022-06-04T16:14:42Z")

</div>

> [@malik](#):
>
> This worked perfectly fine

Malik, @aivarpaalberg’s proposed code will only sort by a single value, ‘`Like`’. The output only looks okay because `COMMENT` and `SAVE` in your sample data are already in order by popularity.

It looks like you need to use @steven.daprano’s code or the tighter version of it that I created. The code I posted immediately above is a complete and very short & clean solution.

_ **Test the code you decide to use with the following data to see if it sorts properly.** _

```python
List = [
        ['30-MAY', 'user1', 'LIKE'],
        ['29-MAY', 'user20', 'COMMENT'],
        ['31-MAY', 'user11', 'SAVE'],
        ['25-MAY', 'user145', 'SAVE'],
        ['27-MAY', 'user16', 'COMMENT'],
        ['28-MAY', 'user5', 'LIKE'],
        ['31-MAY', 'user3', 'LIKE'],
        ['1-JUNE', 'user8', 'LIKE'],
        ['23-MAY', 'user90', 'LIKE'],
        ['1-JUNE', 'user12', 'COMMENT'],
        ['1-JUNE', 'user89', 'SAVE'],
       ]

```

---

<div class="post-metadata">

**Author:** ![aivarpaalberg](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/aivarpaalberg/32/9457_2.png) [@aivarpaalberg](https://discuss.python.org/u/aivarpaalberg)\
**Post date:** [June 5, 2022, 5:26am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/13 "2022-06-05T05:26:47Z")

</div>

> [@mlgtechuser](#):
>
> Malik, @aivarpaalberg’s proposed code will only sort by a single value, ‘`Like`’.

This is not correct to state that it will sort by single value ‘LIKE’. It does sort all the values but gives priority to ‘LIKE’. Sorting of lists is performed by default Python rules - first item in list is compared, if they are equal then second and so on.

If the objective is to sort lists by last item and give priority to ‘LIKE’ then minor adjustment of code could deliver it:

```python
def sort_with_priority(data, priority):
    def helper(record):
        if (key := record[-1]) == priority:
            return (0, key)
        return (1, key)
    return sorted(data, key=helper) # or data.sort(key=helper) for inplace sorting

```

This puts ‘LIKE’ first and then sorts (groups) by last item in alphabetical order. This may or may not be what is wanted.

---

<div class="post-metadata">

**Author:** ![mlgtechuser](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mlgtechuser/32/7310_2.png) [@mlgtechuser](https://discuss.python.org/u/mlgtechuser)\
**Post date:** [June 5, 2022, 5:56am UTC](https://discuss.python.org/t/lists-sorting-a-list/16144/14 "2022-06-05T05:56:59Z")

</div>

It seems very likely that @malik wants to sort the entire list by _ **frequency** of each ‘action’ value_.

Maybe I should have said “Aivar’s code only groups the `'LIKE'` entries.” I was only pointing out that the `'COMMENT'` and `'SAVE'` entries are unchanged and only the `'LIKE'` entries are moved to the top.

This is what I got when running the code from your post on completely randomized log entries. Do you get the same?  
 ![Screenshot_20220605-145211_Pydroid 3](https://us1.discourse-cdn.com/flex002/uploads/python1/original/2X/7/7b1c95112d8a306f41d525f2943ba03702f06567.jpeg)

(Apologies for the screenshot; I am on the mobile app and both of my Android Python interpreters do not allow output text copying.)
