pydash

repository·develop·Indexed 23 days ago

https://github.com/dgilland/pydash

A 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.

Tokens
33.7K
Snippets
188
Records
230
Agent score
78%

What's inside pydash

  1. Overview of pydash

    develop
    pydash is a comprehensive Python utility library designed for performing various tasks in a functional programming style. It is heavily inspired by the Lo-Dash JavaScript library, providing a wide range of tools for data manipulation and functional utilities.
  2. Use Shallow Property Style for callbacks

    develop

    You 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'])
  3. How method chaining and late method chaining work in pydash

    develop

    Pydash supports two primary ways to chain operations using the py_ or _ instances:

    1. Method Chaining: You wrap a data structure in py_(data) and call methods sequentially. You must call .value() at the end to resolve the chain and get the final result.
    2. Late Method Chaining: You start with an empty instance 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])
  4. Use Callable Style for callbacks

    develop

    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:

    1. item: The current element of the collection.
    2. index: The index of the element (for lists) or the key (for dicts).
    3. 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)
  5. Use Deep Property Style for callbacks

    develop

    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')
  6. Use Matches Property Style for callbacks

    develop

    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])
  7. How lazy evaluation works in method chains

    develop

    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()
  8. Using the py_ instance for method calling and chaining

    develop

    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]
  9. Reuse chains with late value passing

    develop

    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]) == 196
  10. Late Value Chaining in pydash

    develop

    Starting 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]