Skip to content

Commit

Permalink
Added dedicated iterator methods for all custom classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
LTLA committed Nov 15, 2023
1 parent 4ce4e6b commit cb31a7a
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 1 deletion.
40 changes: 40 additions & 0 deletions src/biocutils/Factor.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,38 @@ def _sanitize_levels(levels: Sequence[str], check: bool = True) -> StringList:
return levels


class FactorIterator:
"""Iterator for a :py:class:`~Factor` object."""

def __init__(self, parent: "Factor"):
"""
Args:
parent: The parent :py:class:`~Factor` object.
"""
self._parent = parent
self._position = 0

def __iter__(self) -> "FactorIterator":
"""
Returns:
The iterator.
"""
return self

def __next__(self) -> Union[str, None]:
"""
Returns:
Level corresponding to the code at the current position, or None
for missing codes.
"""
if self._position >= len(self._parent):
raise StopIteration
else:
val = self._parent.get_value(self._position)
self._position += 1
return val


class Factor:
"""Factor class, equivalent to R's ``factor``.
Expand Down Expand Up @@ -220,6 +252,14 @@ def __len__(self) -> int:
"""
return len(self._codes)

def __iter__(self) -> FactorIterator:
"""
Returns:
An iterator over the factor. This will iterate over the codes and
report the corresponding level (or None).
"""
return FactorIterator(self)

def __repr__(self) -> str:
"""
Returns:
Expand Down
7 changes: 7 additions & 0 deletions src/biocutils/NamedList.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ def __len__(self) -> int:
"""
return len(self._data)

def __iter__(self) -> "list_iterator":
"""
Returns:
An iterator on the underlying list of data.
"""
return iter(self._data)

def __repr__(self) -> str:
"""
Returns:
Expand Down
7 changes: 7 additions & 0 deletions src/biocutils/Names.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ def __len__(self) -> int:
"""
return len(self._names)

def __iter__(self) -> "list_iterator":
"""
Returns:
An iterator on the underlying list of names.
"""
return iter(self._names)

def __repr__(self) -> str:
"""
Returns:
Expand Down
10 changes: 9 additions & 1 deletion tests/test_Factor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import numpy


def test_Factor_init():
def test_factor_init():
f = Factor([0, 1, 2, 0, 2, 4], levels=["A", "B", "C", "D", "E"])
assert len(f) == 6
assert list(f) == ["A", "B", "C", "A", "C", "E"]
Expand Down Expand Up @@ -40,6 +40,14 @@ def test_Factor_init():
assert f.get_names().as_list() == ["1", "2", "3", "4", "5", "6"]


def test_factor_iter():
f = Factor([0, 1, 2, -1, 2, 4], levels=["A", "B", "C", "D", "E"])
output = []
for y in f:
output.append(y)
assert output == ["A", "B", "C", None, "C", "E"]


def test_Factor_print():
f = Factor([0, 1, 2, 0, 2, 4], levels=["A", "B", "C", "D", "E"])
assert repr(f).startswith("Factor(")
Expand Down
8 changes: 8 additions & 0 deletions tests/test_NamedList.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ def test_NamedList_init():
assert x.get_names() is None


def test_Names_iter():
x = NamedList([1,2,3,4])
output = []
for y in x:
output.append(y)
assert output == [1,2,3,4]


def test_NamedList_get_value():
x = NamedList([1,2,3,4])
assert x.get_value(0) == 1
Expand Down
8 changes: 8 additions & 0 deletions tests/test_Names.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ def test_Names_init():
assert isinstance(empty, Names)


def test_Names_iter():
x = Names([1,2,3,4])
output = []
for y in x:
output.append(y)
assert output == ["1", "2", "3", "4"]


def test_Names_getters():
x = Names([1,2,3,4])
assert x.get_value(0) == "1"
Expand Down

0 comments on commit cb31a7a

Please sign in to comment.