Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

### New Features

- Implemented `map_not_none` map function that excludes from sequence elements mapped to `None`
- Added `first_or_none`, a function to match `head_or_none`
- Added run_test.sh script
- Added [parametrize](https://pypi.org/project/parametrize/) for parameterized unit tests
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ complete documentation reference
| Function | Description | Type |
|---------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------|
| `map(func)/select(func)` | Maps `func` onto elements of sequence | transformation |
| `map_not_none(func)` | Maps `func` onto elements of sequence, filtering out resultant `None` values | transformation |
| `starmap(func)/smap(func)` | Applies `func` to sequence with `itertools.starmap` | transformation |
| `filter(func)/where(func)` | Filters elements of sequence to only those where `func(element)` is `True` | transformation |
| `filter_not(func)` | Filters elements of sequence to only those where `func(element)` is `False` | transformation |
Expand Down
12 changes: 12 additions & 0 deletions functional/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,18 @@ def map(self, func: Callable[[_T_co], _T]) -> Sequence[_T]:
"""
return self._transform(transformations.map_t(func))

def map_not_none(self, func: Callable[[_T_co], _T]) -> Sequence[_T]:
"""
Maps func onto the elements of the sequence, returning only the non-None values.

>>> seq([1, 2, 3, 4, 5]).map_not_none(lambda x: None if x % 2 == 0 else x * -1)
[-1, -3, -5]

:param func: function to map with
:return: sequence with func mapped onto it excluding None values
"""
return self._transform(transformations.map_not_none_t(func))

def select(self, func: Callable[[_T_co], _T]) -> Sequence[_T]:
"""
Selects f from the elements of the sequence.
Expand Down
13 changes: 13 additions & 0 deletions functional/test/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,19 @@ def test_map(self):
self.assertIteratorEqual(expect, result)
self.assert_type(result)

@parametrize(
"sequence, expected",
[
([1, 2, 3, 4, 5], [-1, -3, -5]),
],
)
def test_map_not_none(self, sequence, expected):
result = self.seq(sequence).map_not_none(
lambda x: None if x % 2 == 0 else x * -1
)
self.assertIteratorEqual(expected, result)
self.assert_type(result)

def test_select(self):
l = [1, 2, 0, 5]
expect = [2, 4, 0, 10]
Expand Down
4 changes: 4 additions & 0 deletions functional/test/test_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ def type_checking() -> None:

t_map: Sequence[int] = seq([1, 2, 3, 4]).map(lambda x: x * -1)

t_map_not_none: Sequence[int] = seq([1, 2, 3, 4]).map_not_none(
lambda x: x * -1 if x else x
)

t_select: Sequence[int] = num_seq.select(lambda x: x * -1)

t_starmap: Sequence[int] = seq([(2, 3), (-2, 1), (0, 10)]).starmap(
Expand Down
20 changes: 20 additions & 0 deletions functional/transformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,26 @@ def select_t(func: Callable):
)


def map_not_none_t(func: Callable):
"""
Transformation for Sequence.map_not_none
:param func: map function
:return: transformation
"""

def map_not_none(map_func, sequence):
for element in sequence:
result = map_func(element)
if result is not None:
yield result

return Transformation(
f"map_not_none({name(func)})",
partial(map_not_none, func),
{ExecutionStrategies.PARALLEL},
)


def starmap_t(func: Callable):
"""
Transformation for Sequence.starmap and Sequence.smap
Expand Down