3.4. Pydash¶

Pydash is the kitchen sink of Python utility libraries for doing “stuff” in a functional way.

!pip install pydash 

3.4.1. Work with List¶

3.4.1.1. pydash.flatten: Flatten a Nested Python List¶

If you want to flatten a nested Python list, use the flatten method:

from pydash import py_

a = [[1, 2], [3, 4, 5]]
py_.flatten(a)
[1, 2, 3, 4, 5]

3.4.1.2. pydash.flatten_deep: Flatten a Deeply Nested Python List¶

If your list is deeply nested, use flatten_deep instead:

b = [[1, 2, [4, 5]], [6, 7]]
py_.flatten_deep(b)
[1, 2, 4, 5, 6, 7]

3.4.1.3. pydash.chunk: Split Elements into Groups¶

If you can flatten a list, can you also turn a flattened list into a nested one? Yes, that could be done with the chunk method:

a = [1, 2, 3, 4, 5]
py_.chunk(a, 2)
[[1, 2], [3, 4], [5]]

3.4.2. Work with Dictionary¶

3.4.2.1. Omit Dictionary’s Attribute¶

To omit an attribute from the dictionary, we can use the omit method:

fruits = {"name": "apple", "color": "red", "taste": "sweet"}
py_.omit(fruits, "name")
{'color': 'red', 'taste': 'sweet'}

3.4.2.2. Get Nested Dictionary’s Attribute¶

How do you get the price of an apple from Walmart that is in season in a nested dictionary like below?

apple = {
    "price": {
        "in_season": {"store": {"Walmart": [2, 4], "Aldi": 1}},
        "out_of_season": {"store": {"Walmart": [3, 5], "Aldi": 2}},
    }
}

Normally, you need to use a lot of brackets to get that information:

apple["price"]["in_season"]["store"]["Walmart"]
[2, 4]

Wouldn’t it be nice if you could use the dot notation instead of brackets? That could be done with the get method:

py_.get(apple, "price.in_season.store.Walmart")
[2, 4]

Cool! You can also get the element in an array using [index] :

py_.get(apple, "price.in_season.store.Walmart[0]")
2

3.4.3. Work with List of Dictionaries¶

3.4.3.1. Find Item Index Using a Function¶

list.index(element) allows you to get the index of the specified element in a list. However, you cannot get the index using a function.

fruits = [
    {"name": "apple", "price": 2},
    {"name": "orange", "price": 2},
    {"name": "grapes", "price": 4},
]
fruits.index({"name": "apple", "price": 2})
0
filter_fruits = lambda fruit: fruit["name"] == "apple"

fruits.index(filter_fruits)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-8-b01bf8b7ae1a> in <module>
      1 filter_fruits = lambda fruit: fruit["name"] == "apple"
      2 
----> 3 fruits.index(filter_fruits)

ValueError: <function <lambda> at 0x7f9880491310> is not in list

To get the index of an element in a list using a function, use the find_index method instead:

py_.find_index(fruits, filter_fruits)
0

3.4.3.2. Find Objects With Matching Style¶

The find_index method allows you to get the index of the object that matches a certain pattern. But what if you want to get the items in a list instead of the index? That could be done with the filter method:

fruits = [
    {"name": "apple", "price": 2},
    {"name": "orange", "price": 2},
    {"name": "grapes", "price": 4},
]
py_.filter_(fruits, {"name": "apple"})
[{'name': 'apple', 'price': 2}]

3.4.3.3. Get Nested Object Value¶

Sometimes your list of dictionaries can be nested like below. How can you get the second price of each apple?

l = [
    {"apple": {"price": [0, 1], "color": "red"}},
    {"apple": {"price": [2, 3], "color": "green"}},
]

That is when the map_ method comes in handy.

py_.map_(l, "apple.price[1]")
[1, 3]

3.4.4. Work with Functions¶

3.4.4.1. Execute a Function n Times¶

You can execute a function n times using the times method. This method is a good alternative to a for loop.

py_.times(4, lambda: "I have just bought some apple")
['I have just bought some apple',
 'I have just bought some apple',
 'I have just bought some apple',
 'I have just bought some apple']
py_.times(4, lambda i: f"I have just bought {i} apple")
['I have just bought 0 apple',
 'I have just bought 1 apple',
 'I have just bought 2 apple',
 'I have just bought 3 apple']

3.4.5. Chaining¶

3.4.5.1. Pydash’s Methods¶

Sometimes you might want to apply several methods to an object. Instead of writing several lines of code, can you apply all methods at once?

That is when method chaining comes in handy. To apply method chaining in an object, use the chain method:

fruits = ["apple", "orange", "grapes"]
(py_.chain(fruits).without("grapes").reject(lambda fruit: fruit.startswith("a")))
<pydash.chaining.Chain at 0x7f027895d1f0>

Note that running the code above will not give us the value.

Only when we add .value() to the end of the chain, the final value is computed:

(
    py_.chain(fruits)
    .without("grapes")
    .reject(lambda fruit: fruit.startswith("a"))
    .value()
)
['orange']

This is called lazy evaluation. Lazy evaluation holds the evaluation of an expression until its value is needed, which avoids repeated evaluation.

3.4.5.2. Customized Methods¶

If you want to use your own methods instead of pydash’s methods, use the map method:

def get_price(fruit):
    prices = {"apple": 2, "orange": 2, "grapes": 4}
    return prices[fruit]
total_price = py_.chain(fruits).map(get_price).sum()
total_price.value()
8

3.4.5.3. Planting a Value¶

To replace the initial value of a chain with another value, use the plant method:

total_price.plant(["apple", "orange"]).value()
4

Cool! We replace ['apple', 'orange', 'grapes'] with ['apple', 'orange'] while using the same chain!