Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/usepy/list/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
from .zip_dict import zip_dict
from .first import first
from .last import last
from .group_by import group_by
from .find import find
from .find_index import find_index
from .intersection import intersection
from .partition import partition
from .take import take, take_right
from .drop import drop, drop_right
from .nth import nth


__all__ = [
Expand All @@ -37,4 +45,15 @@
"zip_dict",
"first",
"last",
]
# New functions
"group_by",
"find",
"find_index",
"intersection",
"partition",
"take",
"take_right",
"drop",
"drop_right",
"nth",
]
49 changes: 49 additions & 0 deletions src/usepy/list/drop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from typing import TypeVar, Sequence, List

T = TypeVar('T')


def drop(arr: Sequence[T], n: int = 1) -> List[T]:
"""
Drops the first n elements from a sequence.

Args:
arr (Sequence[T]): The sequence to drop from.
n (int): The number of elements to drop. Defaults to 1.

Returns:
List[T]: A new list without the first n elements.

Examples:
>>> drop([1, 2, 3, 4, 5], 2)
[3, 4, 5]
>>> drop([1, 2, 3], 0)
[1, 2, 3]
>>> drop([1, 2, 3], 10)
[]
"""
return list(arr[n:])


def drop_right(arr: Sequence[T], n: int = 1) -> List[T]:
"""
Drops the last n elements from a sequence.

Args:
arr (Sequence[T]): The sequence to drop from.
n (int): The number of elements to drop from the end. Defaults to 1.

Returns:
List[T]: A new list without the last n elements.

Examples:
>>> drop_right([1, 2, 3, 4, 5], 2)
[1, 2, 3]
>>> drop_right([1, 2, 3], 0)
[1, 2, 3]
>>> drop_right([1, 2, 3], 10)
[]
"""
if n <= 0:
return list(arr)
return list(arr[:-n]) if n < len(arr) else []
29 changes: 29 additions & 0 deletions src/usepy/list/find.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from typing import TypeVar, Sequence, Callable, Optional

T = TypeVar('T')


def find(arr: Sequence[T], predicate: Callable[[T], bool], default: Optional[T] = None) -> Optional[T]:
"""
Finds the first element in a sequence that satisfies a predicate function.

Args:
arr (Sequence[T]): The sequence to search.
predicate (Callable[[T], bool]): A function that returns True for the desired element.
default (Optional[T]): The value to return if no element is found. Defaults to None.

Returns:
Optional[T]: The first element that satisfies the predicate, or default if not found.

Examples:
>>> find([1, 2, 3, 4], lambda x: x > 2)
3
>>> find([1, 2, 3], lambda x: x > 10, default=0)
0
>>> find([], lambda x: x > 0)
None
"""
for item in arr:
if predicate(item):
return item
return default
28 changes: 28 additions & 0 deletions src/usepy/list/find_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import TypeVar, Sequence, Callable

T = TypeVar('T')


def find_index(arr: Sequence[T], predicate: Callable[[T], bool]) -> int:
"""
Finds the index of the first element in a sequence that satisfies a predicate function.

Args:
arr (Sequence[T]): The sequence to search.
predicate (Callable[[T], bool]): A function that returns True for the desired element.

Returns:
int: The index of the first element that satisfies the predicate, or -1 if not found.

Examples:
>>> find_index([1, 2, 3, 4], lambda x: x > 2)
2
>>> find_index([1, 2, 3], lambda x: x > 10)
-1
>>> find_index([], lambda x: x > 0)
-1
"""
for i, item in enumerate(arr):
if predicate(item):
return i
return -1
30 changes: 30 additions & 0 deletions src/usepy/list/group_by.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import TypeVar, Sequence, Callable, Dict, List

T = TypeVar('T')
K = TypeVar('K')


def group_by(arr: Sequence[T], key_func: Callable[[T], K]) -> Dict[K, List[T]]:
"""
Groups elements of a sequence by a key generated from a function.

Args:
arr (Sequence[T]): The sequence to group.
key_func (Callable[[T], K]): A function that generates a key from each element.

Returns:
Dict[K, List[T]]: A dictionary where keys are the generated keys and values are lists of elements.

Examples:
>>> group_by([1, 2, 3, 4, 5], lambda x: x % 2)
{1: [1, 3, 5], 0: [2, 4]}
>>> group_by(['apple', 'banana', 'apricot'], lambda x: x[0])
{'a': ['apple', 'apricot'], 'b': ['banana']}
"""
result: Dict[K, List[T]] = {}
for item in arr:
key = key_func(item)
if key not in result:
result[key] = []
result[key].append(item)
return result
39 changes: 39 additions & 0 deletions src/usepy/list/intersection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from typing import TypeVar, Sequence, List, Iterable

T = TypeVar('T')


def intersection(*arrays: Iterable[T]) -> List[T]:
"""
Returns the intersection of multiple arrays.

The order of the result is determined by the first array.

Args:
*arrays (Iterable[T]): The arrays to intersect.

Returns:
List[T]: A new array of values that are in all given arrays.

Examples:
>>> intersection([1, 2, 3], [2, 3, 4], [2, 3, 5])
[2, 3]
>>> intersection([1, 2, 3], [4, 5, 6])
[]
>>> intersection([1, 2, 2, 3], [2, 3])
[2, 3]
"""
if not arrays:
return []

# Convert all arrays to sets for efficient lookup
sets = [set(arr) for arr in arrays[1:]]

result = []
seen = set()
for item in arrays[0]:
if item not in seen and all(item in s for s in sets):
result.append(item)
seen.add(item)

return result
34 changes: 34 additions & 0 deletions src/usepy/list/nth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from typing import TypeVar, Sequence, Optional

T = TypeVar('T')


def nth(arr: Sequence[T], n: int, default: Optional[T] = None) -> Optional[T]:
"""
Gets the element at index n of a sequence. Supports negative indices.

Args:
arr (Sequence[T]): The sequence to query.
n (int): The index of the element to return. Negative indices count from the end.
default (Optional[T]): The value to return if index is out of bounds. Defaults to None.

Returns:
Optional[T]: The element at index n, or default if out of bounds.

Examples:
>>> nth([1, 2, 3, 4, 5], 1)
2
>>> nth([1, 2, 3, 4, 5], -1)
5
>>> nth([1, 2, 3], 10, default=0)
0
>>> nth([], 0)
None
"""
if not arr:
return default

try:
return arr[n]
except IndexError:
return default
34 changes: 34 additions & 0 deletions src/usepy/list/partition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from typing import TypeVar, Sequence, Callable, Tuple, List

T = TypeVar('T')


def partition(arr: Sequence[T], predicate: Callable[[T], bool]) -> Tuple[List[T], List[T]]:
"""
Partitions a sequence into two lists based on a predicate function.

Args:
arr (Sequence[T]): The sequence to partition.
predicate (Callable[[T], bool]): A function that returns True for elements to be in the first list.

Returns:
Tuple[List[T], List[T]]: A tuple of two lists - elements that satisfy the predicate and those that don't.

Examples:
>>> partition([1, 2, 3, 4, 5], lambda x: x % 2 == 0)
([2, 4], [1, 3, 5])
>>> partition(['a', 'bb', 'ccc'], lambda x: len(x) > 1)
(['bb', 'ccc'], ['a'])
>>> partition([], lambda x: x > 0)
([], [])
"""
matches: List[T] = []
rest: List[T] = []

for item in arr:
if predicate(item):
matches.append(item)
else:
rest.append(item)

return matches, rest
49 changes: 49 additions & 0 deletions src/usepy/list/take.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from typing import TypeVar, Sequence, List

T = TypeVar('T')


def take(arr: Sequence[T], n: int = 1) -> List[T]:
"""
Takes the first n elements from a sequence.

Args:
arr (Sequence[T]): The sequence to take from.
n (int): The number of elements to take. Defaults to 1.

Returns:
List[T]: A new list with the first n elements.

Examples:
>>> take([1, 2, 3, 4, 5], 2)
[1, 2]
>>> take([1, 2, 3], 0)
[]
>>> take([1, 2, 3], 10)
[1, 2, 3]
"""
return list(arr[:n])


def take_right(arr: Sequence[T], n: int = 1) -> List[T]:
"""
Takes the last n elements from a sequence.

Args:
arr (Sequence[T]): The sequence to take from.
n (int): The number of elements to take from the end. Defaults to 1.

Returns:
List[T]: A new list with the last n elements.

Examples:
>>> take_right([1, 2, 3, 4, 5], 2)
[4, 5]
>>> take_right([1, 2, 3], 0)
[]
>>> take_right([1, 2, 3], 10)
[1, 2, 3]
"""
if n <= 0:
return []
return list(arr[-n:]) if n < len(arr) else list(arr)
Loading
Loading