CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pydash

A comprehensive Python utility library for functional programming inspired by JavaScript's Lo-Dash

Pending
Overview
Eval results
Files

chaining.mddocs/

Chaining Module

The Chaining module provides method chaining functionality that enables fluent interface patterns for composing multiple pydash operations in a readable, left-to-right manner. This module consists of 3 main components plus the chaining class.

Core Chaining Functions

chain

def chain(value: Any = None) -> _Dash

Creates a _Dash object which wraps value to enable method chaining.

Parameters:

  • value (Any, optional): Value to wrap for chaining.

Returns:

  • _Dash: Chaining wrapper object.

Example:

from pydash import chain

result = chain([1, 2, 3, 4, 5, 6])\
    .filter(lambda x: x % 2 == 0)\
    .map(lambda x: x * 2)\
    .value()
# [4, 8, 12]

# Complex data processing
data = [
    {'name': 'John', 'age': 30, 'salary': 50000},
    {'name': 'Jane', 'age': 25, 'salary': 60000},
    {'name': 'Bob', 'age': 35, 'salary': 45000}
]

result = chain(data)\
    .filter(lambda x: x['age'] > 25)\
    .sort_by('salary')\
    .map('name')\
    .value()
# ['Bob', 'John']

_ (underscore alias)

def _(value: Any = None) -> _Dash

Shorthand alias for the chain function. Creates a _Dash object for method chaining.

Parameters:

  • value (Any, optional): Value to wrap for chaining.

Returns:

  • _Dash: Chaining wrapper object.

Example:

from pydash import _

# Same functionality as chain()
result = _([1, 2, 3, 4, 5])\
    .filter(lambda x: x > 2)\
    .map(lambda x: x ** 2)\
    .sum_()\
    .value()
# 50 (3² + 4² + 5² = 9 + 16 + 25)

tap

def tap(value: Any, interceptor: Callable) -> Any

Invokes interceptor with value and returns value. This method is useful for debugging intermediate values in a chain.

Parameters:

  • value (Any): Value to pass to interceptor and return.
  • interceptor (Callable): Function to invoke with value.

Returns:

  • Any: Returns value.

Example:

from pydash import tap, _

# Debug intermediate results in a chain
result = _([1, 2, 3, 4, 5])\
    .filter(lambda x: x % 2 == 1)\
    .tap(lambda x: print(f"After filter: {x}"))\
    .map(lambda x: x ** 2)\
    .tap(lambda x: print(f"After map: {x}"))\
    .value()
# Output: After filter: [1, 3, 5]
#         After map: [1, 9, 25]
# Result: [1, 9, 25]

# Using tap for side effects
def log_progress(data):
    print(f"Processing {len(data)} items")
    return data

result = _(data)\
    .filter(condition)\
    .tap(log_progress)\
    .map(transform)\
    .value()

Chaining Class

_Dash

class _Dash:
    def __init__(self, value: Any = None)

The main chaining class that wraps values to enable method chaining. All pydash functions are available as methods on _Dash instances.

Parameters:

  • value (Any, optional): Initial value to wrap.

Key Methods:

  • .value(): Unwraps and returns the final result
  • All pydash functions are available as methods
  • Supports chaining of multiple operations

Example:

from pydash import _

# Create a _Dash instance
wrapper = _([1, 2, 3, 4, 5])

# Chain operations
result = wrapper\
    .filter(lambda x: x > 2)\
    .map(lambda x: x * 2)\
    .reverse()\
    .value()
# [10, 8, 6]

Chaining Patterns and Usage

Basic Chaining

from pydash import _

# Simple transformation chain
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

result = _(numbers)\
    .filter(lambda x: x % 2 == 0)\
    .map(lambda x: x ** 2)\
    .take(3)\
    .value()
# [4, 16, 36]

Object Processing Chains

from pydash import _

users = [
    {'name': 'John', 'age': 30, 'active': True, 'department': 'Engineering'},
    {'name': 'Jane', 'age': 25, 'active': True, 'department': 'Marketing'},
    {'name': 'Bob', 'age': 35, 'active': False, 'department': 'Engineering'},
    {'name': 'Alice', 'age': 28, 'active': True, 'department': 'Sales'}
]

# Complex object processing
active_eng_names = _(users)\
    .filter({'active': True})\
    .filter(lambda u: u['department'] == 'Engineering')\
    .map('name')\
    .value()
# ['John']

# Grouping and aggregation
dept_summary = _(users)\
    .filter({'active': True})\
    .group_by('department')\
    .map_values(lambda group: {\
        'count': len(group),\
        'avg_age': sum(u['age'] for u in group) / len(group)\
    })\
    .value()

String Processing Chains

from pydash import _

text = "  Hello, World! This is a test.  "

processed = _(text)\
    .trim()\
    .to_lower()\
    .replace('!', '')\
    .split(' ')\
    .filter(lambda x: len(x) > 2)\
    .map(lambda x: x.capitalize())\
    .join(' ')\
    .value()
# "Hello World This Test"

Statistical Analysis Chains

from pydash import _

data = [
    {'product': 'A', 'sales': 100, 'region': 'North'},
    {'product': 'B', 'sales': 150, 'region': 'South'},
    {'product': 'A', 'sales': 120, 'region': 'South'},
    {'product': 'C', 'sales': 200, 'region': 'North'},
    {'product': 'B', 'sales': 80, 'region': 'North'}
]

# Calculate total sales by product
product_totals = _(data)\
    .group_by('product')\
    .map_values(lambda group: sum(item['sales'] for item in group))\
    .to_pairs()\
    .sort_by(lambda x: x[1])\
    .reverse()\
    .value()
# [('C', 200), ('B', 230), ('A', 220)]

# Statistical summary
stats = _(data)\
    .map('sales')\
    .thru(lambda sales: {\
        'total': _(sales).sum_().value(),\
        'average': _(sales).mean().value(),\
        'max': _(sales).max_().value(),\
        'min': _(sales).min_().value()\
    })\
    .value()

Debugging Chains with tap

from pydash import _

def debug_print(label):
    def printer(data):
        print(f"{label}: {data}")
        return data
    return printer

result = _([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\
    .tap(debug_print("Initial"))\
    .filter(lambda x: x % 2 == 0)\
    .tap(debug_print("After filter"))\
    .map(lambda x: x ** 2)\
    .tap(debug_print("After map"))\
    .take(3)\
    .tap(debug_print("After take"))\
    .value()

# Output:
# Initial: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# After filter: [2, 4, 6, 8, 10]
# After map: [4, 16, 36, 64, 100]
# After take: [4, 16, 36]

Conditional Chaining

from pydash import _

def conditional_process(data, include_filter=True, sort_desc=False):
    chain_obj = _(data)
    
    # Conditional filtering
    if include_filter:
        chain_obj = chain_obj.filter(lambda x: x > 0)
    
    # Conditional sorting
    if sort_desc:
        chain_obj = chain_obj.sort().reverse()
    else:
        chain_obj = chain_obj.sort()
    
    return chain_obj.value()

data = [3, -1, 4, -2, 5, 0]
result1 = conditional_process(data, True, True)   # [5, 4, 3] (filtered & desc)
result2 = conditional_process(data, False, False) # [-2, -1, 0, 3, 4, 5] (all & asc)

Method Availability

All pydash functions are available as methods on _Dash instances:

Array Methods

_([1, 2, 3, 4]).chunk(2).flatten().uniq().compact().value()

Collection Methods

_(users).filter({'active': True}).map('name').sort_by().value()

Object Methods

_(obj).pick('name', 'age').merge(other_obj).value()

String Methods

_('hello world').camel_case().capitalize().value()

Numerical Methods

_([1, 2, 3, 4, 5]).mean().value()

Function Methods

_(func).once().debounce(100).value()

Predicate Methods

_(value).is_string().value()  # Note: predicates return boolean, not chainable

Utility Methods

_(data).default_to('fallback').times(3).value()

Performance Considerations

Chaining creates intermediate wrapper objects, so for simple operations, direct function calls may be more efficient:

# For simple operations, direct calls may be better
from pydash import map_, filter_

# Direct (more efficient for simple cases)
result = map_(filter_([1, 2, 3, 4], lambda x: x > 2), lambda x: x * 2)

# Chained (better for complex operations)
result = _([1, 2, 3, 4]).filter(lambda x: x > 2).map(lambda x: x * 2).value()

Error Handling in Chains

from pydash import _, attempt

def safe_chain(data):
    try:
        return _(data)\
            .filter(lambda x: x is not None)\
            .map(lambda x: int(x) if isinstance(x, str) else x)\
            .filter(lambda x: x > 0)\
            .value()
    except Exception as e:
        print(f"Chain processing failed: {e}")
        return []

# Using attempt for individual operations
result = _(data)\
    .map(lambda x: attempt(int, x))\
    .filter(lambda x: not isinstance(x, Exception))\
    .value()

The Chaining module enables fluent, readable data processing pipelines by allowing all pydash functions to be chained together in a natural left-to-right flow. This approach is particularly powerful for complex data transformations, filtering operations, and functional programming patterns.

Install with Tessl CLI

npx tessl i tessl/pypi-pydash

docs

arrays.md

chaining.md

collections.md

functions.md

index.md

numerical.md

objects.md

predicates.md

strings.md

utilities.md

tile.json