Overview of pydash
developLo-Dash JavaScript library, providing a wide range of tools for data manipulation and functional utilities.repository·develop·Indexed 23 days ago
https://github.com/dgilland/pydashA functional utility library for Python inspired by the JavaScript Lo-Dash library. It provides a comprehensive set of tools for data manipulation and functional programming patterns, featuring a 'py_' instance for method chaining, lazy evaluation, and support for deep path strings to access nested data in dictionaries and lists.
Lo-Dash JavaScript library, providing a wide range of tools for data manipulation and functional utilities.Beyond the core Lodash port, pydash includes functionality from the following libraries:
lodashcontriblodashdeeplodashmathunderscorestringYou can specify a callback as a single-item list containing the property name you want to extract from each element. This is a shorthand for using pydash.utilities.prop internally.
users = [
{'name': 'Michelangelo', 'active': False},
{'name': 'Donatello', 'active': False},
{'name': 'Leonardo', 'active': True}
]
# Returns the value of the 'active' key for each element
pydash.find_index(users, ['active'])Pydash supports two primary ways to chain operations using the py_ or _ instances:
py_(data) and call methods sequentially. You must call .value() at the end to resolve the chain and get the final result.py_(), call your desired transformation methods, and finally pass the data as a function call to the resulting object. This is useful for creating reusable transformation pipelines that can be applied to different datasets later.# Method chaining
py_([1, 2, 3, 4]).without(2, 3).reject(lambda x: x > 1).value()
# Late method chaining
py_().without(2, 3).reject(lambda x: x > 1)([1, 2, 3, 4])pydash.utilities.memoize uses all passed-in arguments as the cache key by default, rather than only using the first argument.The most direct way to provide a callback is using a regular callable object (like a lambda or a function defined with def).
Pydash attempts to infer the number of arguments your callable supports and will only pass that many arguments. For most functions, the arguments are passed in the following order:
item: The current element of the collection.index: The index of the element (for lists) or the key (for dicts).obj: The original collection being processed.If pydash fails to infer the argument count correctly, wrap your logic in a lambda to explicitly define the signature.
users = [
{'name': 'Michelangelo', 'active': False},
{'name': 'Donatello', 'active': False},
{'name': 'Leonardo', 'active': True}
]
# Single argument callback (item)
callback = lambda item: item['name'] == 'Donatello'
pydash.find_index(users, callback)
# Two argument callback (item, index)
callback = lambda item, index: index == 3
pydash.find_index(users, callback)
# Three argument callback (item, index, obj)
callback = lambda item, index, obj: obj[index]['active']
pydash.find_index(users, callback)For nested objects, you can specify a callback using a deep property string (a path). This uses pydash.utilities.deep_prop internally to resolve the value at that path.
users = [
{'name': 'Michelangelo', 'location': {'city': 'Rome'}},
{'name': 'Donatello', 'location': {'city': 'Florence'}},
{'name': 'Leonardo', 'location': {'city': 'Amboise'}}
]
# Extracts the nested 'city' value from the 'location' object
pydash.map_(users, 'location.city')To check if an element has a specific property with a specific value, use a two-item list containing [property_key, expected_value]. This returns True if the element's key matches the value, otherwise False. This uses pydash.utilities.matches_property internally.
users = [
{'name': 'Michelangelo', 'active': False},
{'name': 'Donatello', 'active': False},
{'name': 'Leonardo', 'active': True}
]
# Returns index of the first user where 'active' is False
pydash.find_index(users, ['active', False])
# Returns index of the last user where 'active' is False
pydash.find_last_index(users, ['active', False])Method chaining in pydash is lazy. When you call a method on a chain, the operation is deferred and not actually executed until you call .value(). This allows you to define a sequence of operations without triggering them immediately.
from pydash import py_
def echo(value):
print(value)
# The for_each operation is not executed yet
lazy = py_([1, 2, 3, 4]).for_each(echo)
# The operations are executed now
result = lazy.value()The py_ instance provides a way to perform both direct method calling and method chaining from a single object. It combines the functionality of pydash.<function> and pydash.chain.
When using method chaining, you must call .value() at the end of the chain to retrieve the final result.
from pydash import py_
# Method calling
py_.initial([1, 2, 3, 4, 5]) == [1, 2, 3, 4]
# Method chaining (requires .value() to resolve)
py_([1, 2, 3, 4, 5]).initial().value() == [1, 2, 3, 4]You can create reusable, ad-hoc functions by initializing a chain without a root value (using py_()). This allows you to define a sequence of operations that can be applied to different inputs later by calling the chain object as a function.
from pydash import py_
# Define a reusable chain function
square_sum = py_().power(2).sum()
# Apply it to different values
assert square_sum([1, 2, 3]) == 14
assert square_sum([4, 5, 6]) == 77
# You can also extend existing chain functions
square_sum_square = square_sum.power(2)
assert square_sum_square([1, 2, 3]) == 196Starting from v3.0.0, pydash supports "Late Value Chaining." This allows you to define a chain of operations without providing the initial root value immediately. You can then reuse this chain template with different values.
To implement this, use py_() to start a chain without a value, and then apply your methods.
>>> from pydash import py_
>>> square_sum = py_().power(2).sum()
>>> [square_sum([1, 2, 3]), square_sum([4, 5, 6]), square_sum([7, 8, 9])]
[14, 77, 194]