API Reference: ListMapper¶
ListMapper[T] is the main eager execution class in functional_list. It wraps a Python list and provides functional-style transformations similar to Apache Spark RDD operations.
Class Signature¶
Construction¶
Direct Construction¶
from functional_list import ListMapper
# Create from individual elements
lm = ListMapper[int](1, 2, 3, 4)
# Create from unpacked iterable
items = [10, 20, 30]
lm = ListMapper[int](*items)
# Type-annotated construction
strings = ListMapper[str]("a", "b", "c")
From Files¶
# CSV
data = ListMapper.from_csv("file.csv", options=CSVReadOptions(...))
# JSON
data = ListMapper.from_json("file.json")
# JSONL
data = ListMapper.from_jsonl("file.jsonl")
# Text
data = ListMapper.from_text("file.txt", options=TextReadOptions(...))
# Parquet (requires pyarrow)
data = ListMapper.from_parquet("file.parquet", columns=[...])
See the I/O Guide for detailed file I/O documentation.
Core Transformation Methods¶
map¶
Apply a function to each element.
Parameters:
- fn: Function to apply to each element
- backend: Optional execution backend
Returns: New ListMapper with transformed elements
Example:
numbers = ListMapper[int](1, 2, 3, 4)
squared = numbers.map(lambda x: x * x)
# Result: List[1, 4, 9, 16]
filter¶
Keep only elements that satisfy a predicate.
Parameters:
- fn: Predicate function (returns True to keep element)
- backend: Optional execution backend
Returns: New ListMapper with filtered elements
Example:
numbers = ListMapper[int](1, 2, 3, 4, 5, 6)
evens = numbers.filter(lambda x: x % 2 == 0)
# Result: List[2, 4, 6]
flat_map¶
Map each element to multiple elements and flatten.
def flat_map(self, fn: Callable[[T], Iterable[U]], *, backend: Optional[Backend] = None) -> ListMapper[U]
Parameters:
- fn: Function that returns an iterable for each element
- backend: Optional execution backend
Returns: New ListMapper with flattened results
Example:
sentences = ListMapper[str]("hello world", "python rocks")
words = sentences.flat_map(lambda s: s.split())
# Result: List['hello', 'world', 'python', 'rocks']
reduce¶
Reduce all elements to a single value.
Parameters:
- fn: Binary reduction function
- backend: Optional execution backend
Returns: Single reduced value
Example:
foreach¶
Execute a function for each element (for side effects).
Parameters:
- fn: Function to execute (return value ignored)
- backend: Optional execution backend
Returns: None
Example:
numbers = ListMapper[int](1, 2, 3)
numbers.foreach(lambda x: print(f"Value: {x}"))
# Prints:
# Value: 1
# Value: 2
# Value: 3
Key-Value Pair Methods¶
These methods work on ListMapper containing tuples (key, value).
group_by_key¶
Group values by their keys.
Returns: ListMapper of (key, [values]) tuples
Example:
pairs = ListMapper(("a", 1), ("b", 2), ("a", 3), ("b", 4))
grouped = pairs.group_by_key()
# Result: List[('a', [1, 3]), ('b', [2, 4])]
reduce_by_key¶
Reduce values for each key.
Parameters:
- fn: Binary reduction function for values
Returns: ListMapper of (key, reduced_value) tuples
Example:
pairs = ListMapper(("a", 1), ("b", 2), ("a", 3), ("b", 4))
sums = pairs.reduce_by_key(lambda x, y: x + y)
# Result: List[('a', 4), ('b', 6)]
group_by¶
Group elements by a key function.
Parameters:
- fn: Function to extract grouping key
Returns: ListMapper of (key, [elements]) tuples
Example:
numbers = ListMapper[int](1, 2, 3, 4, 5, 6)
by_parity = numbers.group_by(lambda x: "even" if x % 2 == 0 else "odd")
# Result: List[('odd', [1, 3, 5]), ('even', [2, 4, 6])]
Sorting and Ordering¶
sort¶
Sort elements.
Parameters:
- key: Optional function to extract comparison key
- reverse: Sort in descending order if True
Returns: New sorted ListMapper
Example:
numbers = ListMapper[int](3, 1, 4, 1, 5, 9)
sorted_asc = numbers.sort()
# Result: List[1, 1, 3, 4, 5, 9]
sorted_desc = numbers.sort(reverse=True)
# Result: List[9, 5, 4, 3, 1, 1]
words = ListMapper[str]("apple", "pie", "a", "cherry")
by_length = words.sort(key=lambda s: len(s))
# Result: List['a', 'pie', 'apple', 'cherry']
Aggregation and Statistics¶
count¶
Count the number of elements.
Example:
sum¶
Sum all numeric elements.
Example:
mean¶
Calculate the arithmetic mean.
Example:
min / max¶
Find minimum or maximum element.
Example:
Set Operations¶
distinct¶
Remove duplicate elements, preserving first occurrence order.
Parameters:
- backend: Optional execution backend
Returns: New ListMapper with unique elements
Example:
numbers = ListMapper[int](1, 2, 2, 3, 3, 3, 4)
unique = numbers.distinct()
# Result: List[1, 2, 3, 4]
# Preserves order of first occurrence
ordered = ListMapper[int](3, 1, 4, 1, 5, 9, 2, 6, 5, 3)
unique = ordered.distinct()
# Result: List[3, 1, 4, 5, 9, 2, 6]
# With backend
from functional_list.backend import LocalBackend
unique = numbers.distinct(backend=LocalBackend(mode="threads"))
sort¶
Sort elements using an optional key function.
def sort(
self,
*,
key: Optional[Callable[[T], Any]] = None,
reverse: bool = False,
backend: Optional[BaseBackend] = None,
) -> ListMapper[T]
Parameters:
- key: Optional function to extract comparison key from each element
- reverse: If True, sort in descending order (default: False)
- backend: Optional execution backend
Returns: New ListMapper with sorted elements
Important Notes: - Sort is stable (maintains relative order of equal elements) - Returns a new ListMapper (immutable operation) - Uses Python's optimized Timsort algorithm - LocalBackend in serial mode uses optional Cython acceleration
Examples:
# Sort numbers in ascending order
numbers = ListMapper(3, 1, 4, 1, 5, 9, 2, 6)
sorted_asc = numbers.sort()
# Result: List[1, 1, 2, 3, 4, 5, 6, 9]
# Sort in descending order
sorted_desc = numbers.sort(reverse=True)
# Result: List[9, 6, 5, 4, 3, 2, 1, 1]
# Sort with key function
words = ListMapper("apple", "pie", "a", "cherry")
by_length = words.sort(key=lambda x: len(x))
# Result: List['a', 'pie', 'apple', 'cherry']
# Sort dictionaries by field
users = ListMapper(
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25},
{"name": "Charlie", "age": 35}
)
by_age = users.sort(key=lambda u: u["age"])
# Result: List[{'name': 'Bob', 'age': 25}, ...]
# Sort by multiple criteria
data = ListMapper(
{"category": "A", "value": 2},
{"category": "B", "value": 1},
{"category": "A", "value": 1}
)
sorted_data = data.sort(key=lambda x: (x["category"], x["value"]))
# Result: Sorted by category, then by value
# Sort with backend
from functional_list.backend import LocalBackend
sorted_nums = numbers.sort(backend=LocalBackend(mode="serial"))
Performance
When using LocalBackend(mode="serial"), the sort operation can use optional Cython acceleration for improved performance on large datasets.
Chaining
Sort integrates seamlessly with method chaining:
union¶
Combine two ListMapper objects of the same type into one.
Parameters:
- other: Another ListMapper to union with
- backend: Optional execution backend (reserved for future optimization)
Returns: New ListMapper containing all elements from both ListMappers
Raises:
- TypeError: If other is not a ListMapper instance
- TypeError: If the ListMappers contain incompatible types
Important Notes:
- Elements from self appear first, followed by elements from other
- Does not remove duplicates - use .union(other).distinct() for that
- Returns a new ListMapper (immutable operation)
- Performs runtime type checking to prevent incompatible unions
Examples:
# Basic union with integers
list1 = ListMapper[int](1, 2, 3)
list2 = ListMapper[int](4, 5, 6)
result = list1.union(list2)
# Result: List[1, 2, 3, 4, 5, 6]
# Union with dictionaries
dict1 = ListMapper({'a': 1}, {'b': 2})
dict2 = ListMapper({'c': 3}, {'d': 4})
result = dict1.union(dict2)
# Result: List[{'a': 1}, {'b': 2}, {'c': 3}, {'d': 4}]
# Union preserves duplicates
list1 = ListMapper[int](1, 2, 3)
list2 = ListMapper[int](3, 4, 5)
result = list1.union(list2)
# Result: List[1, 2, 3, 3, 4, 5]
# Remove duplicates after union
result = list1.union(list2).distinct()
# Result: List[1, 2, 3, 4, 5]
# Type checking - this raises TypeError
int_list = ListMapper[int](1, 2, 3)
str_list = ListMapper[str]("a", "b", "c")
int_list.union(str_list) # TypeError: incompatible types
# With backend (for future optimization)
from functional_list.backend import LocalBackend
result = list1.union(list2, backend=LocalBackend(mode="threads"))
Type Safety
The union method performs runtime type checking. Attempting to union ListMappers with incompatible types (e.g., ListMapper[int] with ListMapper[str]) will raise a TypeError.
Chaining Operations
Union works seamlessly with method chaining:
intersection¶
Get elements present in both ListMappers.
Example:
a = ListMapper[int](1, 2, 3, 4)
b = ListMapper[int](3, 4, 5, 6)
common = a.intersection(b)
# Result: List[3, 4]
Sampling and Partitioning¶
take¶
Get first n elements.
Example:
sample¶
Get random sample of n elements.
Parameters:
- n: Number of elements to sample
- seed: Optional random seed for reproducibility
Example:
Lazy Evaluation¶
lazy¶
Convert to lazy evaluation mode.
Returns: LazyListMapper that defers computation
Example:
lazy_pipeline = (
ListMapper[int](1, 2, 3, 4)
.lazy()
.map(lambda x: x * x)
.filter(lambda x: x > 5)
)
result = lazy_pipeline.collect() # Execute and return ListMapper
See LazyListMapper API for lazy-specific methods.
Conversion Methods¶
to_list¶
Convert to Python list.
Example:
to_json¶
Write to JSON file.
Example:
to_jsonl¶
Write to JSONL file.
Example:
List Compatibility¶
ListMapper supports standard Python list operations:
Indexing and Slicing¶
lm = ListMapper[int](10, 20, 30, 40, 50)
# Indexing
first = lm[0] # 10
last = lm[-1] # 50
# Slicing
middle = lm[1:4] # List[20, 30, 40]
every_other = lm[::2] # List[10, 30, 50]
Length¶
Iteration¶
Membership¶
Append and Extend¶
lm = ListMapper[int](1, 2, 3)
lm.append(4) # List[1, 2, 3, 4]
lm.extend([5, 6]) # List[1, 2, 3, 4, 5, 6]
Backend Support¶
All transformation methods (map, filter, foreach, reduce, flat_map) accept an optional backend parameter:
from functional_list import ListMapper, LocalBackend, RayBackend
lm = ListMapper[int](*range(1000))
# Use threading
result = lm.map(fn, backend=LocalBackend(mode="threads", workers=4))
# Use multiprocessing
result = lm.map(fn, backend=LocalBackend(mode="processes", workers=4))
# Use Ray (if installed)
result = lm.map(fn, backend=RayBackend(num_cpus=8))
See the Backends Guide for detailed information.
Global Backend Configuration¶
set_default_backend¶
Set default backend for all operations.
Example:
from functional_list import ListMapper, LocalBackend
ListMapper.set_default_backend(LocalBackend(mode="threads", workers=8))
# Now all operations use threading by default
result = ListMapper[int](1, 2, 3).map(lambda x: x * 2)
using_backend¶
Temporary backend context manager.
Example:
from functional_list import ListMapper, LocalBackend
with ListMapper.using_backend(LocalBackend(mode="threads")):
result = ListMapper[int](1, 2, 3).map(lambda x: x * 2)
# Uses threading
# Outside context, uses default backend
Type Safety¶
ListMapper is fully typed and works with type checkers:
from functional_list import ListMapper
# Type checker knows this is ListMapper[int]
numbers: ListMapper[int] = ListMapper[int](1, 2, 3)
# Type checker knows this is ListMapper[str]
strings: ListMapper[str] = numbers.map(str)
# Type error: incompatible types
# numbers.map(lambda x: "str") # OK
# strings.map(lambda x: x + 1) # Type error!
See Also¶
- LazyListMapper API - Lazy evaluation mode
- Backends API - Execution backend reference
- Backends Guide - How to use backends
- I/O Guide - File operations