0% found this document useful (0 votes)
3 views5 pages

sorted using function

my python notes
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views5 pages

sorted using function

my python notes
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

Got it — you’re asking about **`sorted(iterable, key=function)`** where instead of

writing `lambda x: ...`, we write our own **custom function** and pass it as `key`.
Let’s go step-by-step with three examples of increasing complexity:

***

## **1) Simple example**


Sort a list of strings by their length.

```python
def by_length(s):
return len(s)

words = ["apple", "kiwi", "banana", "fig"]


result = sorted(words, key=by_length)
print(result)
# Output: ['fig', 'kiwi', 'apple', 'banana']
```
📌 **What happens:**
- Python calls `by_length()` for each item.
- The `sorted()` function uses those returned values to determine the order.

***

## **2) Medium example**


Sort a list of tuples `(name, age)` by **age descending**, then by **name
alphabetically**.

```python
def sort_by_age_then_name(person):
name, age = person
return (-age, name) # negative for descending age, name for alphabetical

people = [("John", 25), ("Alice", 30), ("Bob", 30), ("Daisy", 22)]


result = sorted(people, key=sort_by_age_then_name)
print(result)
# Output: [('Alice', 30), ('Bob', 30), ('John', 25), ('Daisy', 22)]
```
📌 **What happens:**
- First, people are sorted by **age** in descending order (`-age`).
- If ages are the same, they are sorted by **name** alphabetically.

***

## **3) Complicated example**


Sort a list of dictionaries representing products by:
1. **Total price** = `price * quantity` (primary key, descending).
2. If equal, sort by **category** alphabetically.
3. If still equal, sort by **name length** ascending.

```python
def product_sort_key(product):
total_price = product['price'] * product['quantity']
return (-total_price, product['category'], len(product['name']))

products = [
{"name": "Widget", "price": 10, "quantity": 5, "category": "Tools"},
{"name": "Gadget", "price": 20, "quantity": 2, "category": "Electronics"},
{"name": "Thing", "price": 10, "quantity": 5, "category": "Electronics"},
{"name": "Device", "price": 3, "quantity": 10, "category": "Toys"}
]

result = sorted(products, key=product_sort_key)


for p in result:
print(p)
```
**Output:**
```
{'name': 'Thing', 'price': 10, 'quantity': 5, 'category': 'Electronics'}
{'name': 'Widget', 'price': 10, 'quantity': 5, 'category': 'Tools'}
{'name': 'Gadget', 'price': 20, 'quantity': 2, 'category': 'Electronics'}
{'name': 'Device', 'price': 3, 'quantity': 10, 'category': 'Toys'}
```
📌 **What happens:**
- Calculates total price for sorting (highest first).
- If tie on price, category decides.
- If tie on category, name length decides.

***

✅ This shows **simple → medium → complex** key functions.


If you like, I can also give you **the same examples in one-liner lambda form** for
quick coding in contests.

Do you want me to do that?


I see what you’re trying to do — the **first one** is fine, but the **second one**
is not syntactically correct in Python.

***

### 1 ✅ Correct:
```python
sorted(words, key=lambda x: len(x))
```
This works fine — it sorts `words` by the length of each element.

***

### 2 ❌ Wrong:
```python
sorted(people, lambda x: -x[1], x[0])
```
This is **invalid** because:
- `sorted()` only allows **one** `key` function, not multiple positional arguments
after the iterable.
- You can’t pass two values (`-x, x`) like that — the key must be a single value.
- If you need multiple sort criteria, you make the `lambda` return a **tuple**.

***

✅ **Corrected version** for your intention (“sort by `-x` then `x`”):


```python
sorted(people, key=lambda x: (-x[1], x[0]))
```
Here:
- The `key` function returns a tuple.
- Sorting in Python is lexicographic for tuples — it first sorts by the first
element (`-x`, i.e., age descending), and if there’s a tie, by the second element
(`x`, i.e., name ascending).

***

### Example:
```python
people = [("John", 25), ("Alice", 30), ("Bob", 30), ("Daisy", 22)]

result = sorted(people, key=lambda x: (-x[1], x[0]))


print(result)
# [('Alice', 30), ('Bob', 30), ('John', 25), ('Daisy', 22)]
```

***

If you like, I can **also show you the equivalent using `operator.itemgetter`** so
that it’s even cleaner.
Do you want me to show that?
Yes — your understanding is correct.

```python
result = sorted(people, key=itemgetter(1, 0), reverse=False)
```

will sort **primarily by age ascending** (`itemgetter(1)` → index `1` in each tuple
is age)
and then, if ages are equal, **by name ascending** (`itemgetter(0)` → index `0` is
name).

***

### Example
```python
from operator import itemgetter

people = [("John", 25), ("Alice", 30), ("Bob", 30), ("Daisy", 22)]


result = sorted(people, key=itemgetter(1, 0), reverse=False)
print(result)
```

**Output:**
```
[('Daisy', 22), ('John', 25), ('Alice', 30), ('Bob', 30)]
```
- Sorted first by `age` ascending: 22, 25, 30, 30
- For the two with age 30, `"Alice"` comes before `"Bob"` alphabetically.

***

📌 **Note:**
- The `reverse=False` explicitly means “ascending order” (the default).
- If you set `reverse=True` here, **both** age and name sorting would be reversed
(age descending, then name descending).

If you want **age descending but name ascending**, `itemgetter` alone isn’t enough
— you’d need the lambda trick:

```python
sorted(people, key=lambda x: (-x[1], x[0]))
```

***

Do you want me to make a small table showing all combinations of


ascending/descending on both fields? That would make it easy to remember.
Here’s a handy summary table for **sorting by two fields** in a list of tuples,
showing all combinations of ascending/descending order for both fields (let’s say
we have `people = [("John", 25), ("Alice", 30), ("Bob", 30), ("Daisy", 22)]`, where
each tuple is `(name, age)`):

| Sort Style | Python Code


| Result |
|:--------------------------|:-----------------------------------------------------
----|:------------------------------------------|
| Age ↑, Name ↑ (both ascending) | `sorted(people, key=itemgetter(1, 0))`
| [('Daisy', 22), ('John', 25), ('Alice', 30), ('Bob', 30)] |
| Age ↓, Name ↑ | `sorted(people, key=lambda x: (-x, x))` |
[('Alice', 30), ('Bob', 30), ('John', 25), ('Daisy', 22)] |
| Age ↑, Name ↓ | `sorted(people, key=lambda x: (x, -ord(x)))`* |
[('Daisy', 22), ('John', 25), ('Bob', 30), ('Alice', 30)] |
| Age ↓, Name ↓ (both descending) | `sorted(people, key=itemgetter(1, 0),
reverse=True)` | [('Bob', 30), ('Alice', 30), ('John', 25), ('Daisy', 22)] |

**Explanations:**
- `itemgetter(1, 0)`: sorts by age (ascending), then name (ascending).
- `lambda x: (-x, x)`: age descending, name ascending.
- To get **descending name**, you'd need a little trick (since strings can’t be
negated directly). A quick hack is to use `-ord(x)` for first letter, but for real
applications, use `reverse=True` on secondary sorting or sort twice (see note
below).
- `reverse=True` with `itemgetter` reverses *both* sorting criteria.

**Note:**
To sort by descending name properly (not just by the first character), you usually
do:
```python
sorted(people, key=lambda x: (x[1], x[0]), reverse=True)
```
But this will reverse age and name.

If you want to combine one ascending and one descending, always use a tuple in a
lambda!

**General rule:**
- For ascending on a field: use as-is.
- For descending on a field: use negative for numbers or reverse strings for text,
or sort items twice.

***

**Summary Example for most common:**

- **Age ascending, name ascending:**


```python
sorted(people, key=itemgetter(1, 0))
```
- **Age descending, name ascending:**
```python
sorted(people, key=lambda x: (-x[1], x[0]))
```
- **Age ascending, name descending:**
```python
sorted(people, key=lambda x: (x[1], x[0]), reverse=True)
```
*(but this reverses both; so more care needed for only name descending)*

Would you like examples for more than two sorting keys? Or examples with
dictionaries/lists instead of tuples?

You might also like