Post

Daily Work Tips

Document repeatable work tips encountered in daily real work, keep updating!

Daily Work Tips

Coding

IPython Underscore Variable

Added on 03/10/2025

Background

I ran a query that took quite some time to complete, and in the meantime, I accidentally truncated a table.😢 Fortunately, IPython’s underscore variable automatically stores the results of previous computations.

The simplest way to access it is by opening a new cell in Jupyter Notebook and typing _ to retrieve the most recent output. IPython supports _ for the previous output, __ for the next previous output, and ___ for the next-next previous output, as detailed in the official documentation.

Please note that running _, __, or ___ are also executions, meaning the values of these variables will be updated after each execution. For this reason, I recommend using only _ to get the most recent result, as its value remains unchanged after the execution.

Of course, the best practice is to store outputs in custom variables for better clarity and reliability.

Usage

Underscore Variable Usage

Microsoft Graph REST API Get Email by User

Added on 03/21/2025

Background

I encountered a request to create an email notification that involved adding a large number of email addresses to a list. However, the stakeholder only provided names.

So instead of searching for usernames in Teams one by one, we can use the Microsoft Graph REST API to retrieve the email addresses in bulk. For API details, please refer to official documentation.

Usage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import requests

def get_user_email(name):

    GRAPH_URL = f"https://graph.microsoft.com/v1.0/users?$filter=displayName eq '{name}'&$select=id,displayName,mail,userPrincipalName"

    ACCESS_TOKEN = # Your token
    HEADERS = {
        "Authorization": f"Bearer {ACCESS_TOKEN}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(GRAPH_URL, headers=HEADERS)
    
    if response.status_code == 200:
        data = response.json()
        users = data.get("value", [])
        # Due to duplicate names, email are not unique. To prevent sending emails to the wrong user, not return email. Can be customized
        if len(users) > 1:
            print(f"Name: {users[0].get('displayName')}, multiple records")
        elif users:
            # print(f"Name: {users[0].get('displayName')}")
            print(f"{users[0].get('mail')}")
        else:
            print("No user found with that name.")
    else:
        print(f"Error: {response.status_code}, {response.text}")

Understanding the sorted() function anew: The Power of the key Parameter

Added on 04/22/2025

Background

Python’s built-in sorted() function is one of the most commonly used tools in programming. It’s based on the Timsort algorithm, which has a time complexity of O(n log n). Its most basic usage is sorting a list in ascending order by default, or sorting in descending order with the reverse parameter.

1
2
3
4
5
6
7
8
9
10
11
test_lst = [3,2,6,9,1,0]

# ascending
sorted_lst = sorted(test_lst)
print(sorted_lst)
# [0,1,2,3,6,9]

# descending
sorted_lst = sorted(test_lst, reverse=True)
print(sorted_lst)
# [9,6,3,2,1,0]

But what if you need to sort based on something other than the natural order of the elements? That’s where the key parameter comes in. The key parameter accepts a function that takes one argument and returns a value that will be used for sorting purposes. This function is applied to each element in the list, and the sorting is done based on these returned values.

In other words, you provide a function that extracts or computes a ‘key’ from each element, and sorted() will sort the elements based on these keys.

Usage

Suppose you have a list of strings and you want to sort them by their length:

1
2
3
4
words = ['apple', 'banana', 'cherry', 'date']
sorted_words = sorted(words, key=len)
print(sorted_words)
# ['date', 'apple', 'banana', 'cherry']

Here, len is a function that takes a string and returns its length. So, sorted() sorts the strings based on their lengths.

In practice, when I need to sort a list of dictionaries, I usually convert it into a DataFrame for further processing. However, in this case, we don’t need any complex data manipulation, just a simple sort. So we can easily use the sorted() function to achieve this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Imagine we have a list of dictionaries
# each representing a playing card with 'suit' and 'num' attributes
# We want to sort these cards first by their number and then by their suit.
card_lst = [
    {"code": "7S", "suit": "SPADES", "num": 7},
    {"code": "2C", "suit": "CLUBS", "num": 2},
    {"code": "AD", "suit": "DIAMONDS", "num": 1},
    {"code": "2D", "suit": "DIAMONDS", "num": 2},
    {"code": "0S", "suit": "SPADES", "num": 10}
]

sorted_lst = sorted(card_lst, key=lambda x: (x['num'], x['suit']))

for card in sorted_lst:
    print(f"{card['num']} of {card['suit']}")

# 1 of DIAMONDS
# 2 of CLUBS
# 2 of DIAMONDS
# 7 of SPADES
# 10 of SPADES

In this example, we use a lambda function as the key. This lambda function takes a dictionary x and returns a tuple (x['num'], x['suit']). When sorted() compares two elements, it compares these tuples. Since tuples are compared in lexicographical order (like dictionary order), it first compares the num values, and if they are equal, it compares the suit values.

This post is licensed under CC BY 4.0 by the author.