Source code for biocutils.subset_sequence

from functools import singledispatch
from typing import Any, Sequence, Union


[docs] @singledispatch def subset_sequence(x: Any, indices: Sequence[int]) -> Any: """Subset a sequence-like object by indices. Subset ``x`` by ``indices`` to obtain a new object. The default method attempts to use ``x``'s ``__getitem__`` method. Args: x: Any object that supports ``__getitem__`` with an integer sequence. indices: Sequence of non-negative integers specifying the positions of interest. All indices should be less than ``len(x)``. Returns: The result of slicing ``x`` by ``indices``. The exact type depends on what ``x``'s ``__getitem__`` method returns. """ return x[indices]
@subset_sequence.register def _subset_sequence_list(x: list, indices: Sequence[int]) -> list: """Subset a list by indices. Args: x: List to subset. indices: Sequence of non-negative integers specifying positions. Returns: A new list containing the specified elements. """ return type(x)(x[i] for i in indices) @subset_sequence.register def _subset_sequence_range(x: range, indices: Sequence[int]) -> Union[list, range]: """Subset a range by indices. Args: x: Range object to subset. indices: Sequence of non-negative integers or a range object. Returns: A range if indices is a range, otherwise a list. """ if isinstance(indices, range): # We can just assume that all 'indices' are in [0, len(x)), # so no need to handle out-of-range indices. return range(x.start + x.step * indices.start, x.start + x.step * indices.stop, x.step * indices.step) else: return [x[i] for i in indices] @subset_sequence.register def _subset_sequence_tuple(x: tuple, indices: Sequence[int]) -> tuple: """Subset a tuple by indices. Args: x: Tuple to subset. indices: Sequence of non-negative integers specifying positions. Returns: A new tuple containing the specified elements. """ return tuple(x[i] for i in indices)