diff --git a/boiling_learning/datasets/cache.py b/boiling_learning/datasets/cache.py index 6a6bcaf7..37164f4f 100644 --- a/boiling_learning/datasets/cache.py +++ b/boiling_learning/datasets/cache.py @@ -7,7 +7,8 @@ from typing_extensions import Literal from boiling_learning.datasets.sliceable import SliceableDatasetCache -from boiling_learning.utils.utils import PathLike, resolve, unsort +from boiling_learning.utils.iterutils import unsort +from boiling_learning.utils.utils import PathLike, resolve _T = TypeVar('_T') diff --git a/boiling_learning/preprocessing/hdf5.py b/boiling_learning/preprocessing/hdf5.py index c579fb7a..60cce792 100644 --- a/boiling_learning/preprocessing/hdf5.py +++ b/boiling_learning/preprocessing/hdf5.py @@ -8,7 +8,8 @@ from boiling_learning.datasets.sliceable import SliceableDataset from boiling_learning.preprocessing.video import VideoFrame -from boiling_learning.utils.utils import PathLike, resolve, unsort +from boiling_learning.utils.iterutils import unsort +from boiling_learning.utils.utils import PathLike, resolve _T = TypeVar('_T') diff --git a/boiling_learning/utils/iterutils.py b/boiling_learning/utils/iterutils.py index 29c28369..2944c2a9 100644 --- a/boiling_learning/utils/iterutils.py +++ b/boiling_learning/utils/iterutils.py @@ -1,4 +1,6 @@ -from typing import Any, Callable, Iterable, List, TypeVar +import itertools +import typing +from typing import Any, Callable, Iterable, List, Tuple, TypeVar import more_itertools as mit import numpy as np @@ -62,8 +64,19 @@ def evenly_spaced_indices( else: raise ValueError('`goal` must be either `"distance"` or `"spread"`') - return np.round(points).astype(int).tolist() + return typing.cast(List[int], np.round(points).astype(int).tolist()) def distance_maximized_evenly_spaced_indices(total: int, count: int) -> List[int]: return evenly_spaced_indices(total, count, goal='distance') + + +def unsort(iterable: Iterable[_T]) -> Tuple[Iterable[int], Iterable[_T]]: + peekable = mit.peekable(iterable) + + if not peekable: + return (), () + + sorted_indices, sorters = mit.sort_together((peekable, itertools.count())) + _, unsorters = mit.sort_together((sorters, itertools.count())) + return unsorters, sorted_indices diff --git a/boiling_learning/utils/utils.py b/boiling_learning/utils/utils.py index 467aef87..0964d123 100644 --- a/boiling_learning/utils/utils.py +++ b/boiling_learning/utils/utils.py @@ -1,6 +1,5 @@ from __future__ import annotations -import itertools import operator import os import random @@ -17,13 +16,11 @@ Mapping, Optional, Sequence, - Tuple, TypeVar, Union, ) import funcy -import more_itertools as mit _T = TypeVar('_T') _Key = TypeVar('_Key') @@ -51,17 +48,6 @@ def argsorted(iterable: Iterable) -> Iterable[int]: return funcy.pluck(0, sorted(enumerate(iterable), key=operator.itemgetter(1))) -def unsort(iterable: Iterable[_T]) -> Tuple[Iterable[int], Iterable[_T]]: - peekable = mit.peekable(iterable) - - if not peekable: - return (), () - - sorted_indices, sorters = mit.sort_together((peekable, itertools.count())) - _, unsorters = mit.sort_together((sorters, itertools.count())) - return unsorters, sorted_indices - - def merge_dicts(*dict_args: Mapping, latter_precedence: bool = True) -> dict: if latter_precedence: dict_args = reversed(dict_args) diff --git a/tests/test_utils_.py b/tests/test_utils_.py index 4c1a448e..c4e0442a 100644 --- a/tests/test_utils_.py +++ b/tests/test_utils_.py @@ -3,27 +3,8 @@ from boiling_learning.utils.collections import KeyedSet from boiling_learning.utils.geometry import Cylinder, RectangularPrism -from boiling_learning.utils.iterutils import evenly_spaced_indices +from boiling_learning.utils.iterutils import evenly_spaced_indices, unsort from boiling_learning.utils.lazy import Lazy, LazyCallable -from boiling_learning.utils.utils import indexify, unsort - - -class utils_utils_test(TestCase): - def test_indexify(self) -> None: - self.assertEqual(tuple(indexify('abc')), (0, 1, 2)) - - def test_unsort(self) -> None: - unsorted_items = [50, 30, 20, 10, 40] - - unsorters, sorted_items = unsort(unsorted_items) - unsorters = list(unsorters) - sorted_items = list(sorted_items) - assert sorted_items == [10, 20, 30, 40, 50] - assert unsorters == [4, 2, 1, 0, 3] - - assert [sorted_items[index] for index in unsorters] == unsorted_items - - assert unsort(()) == ((), ()) class utils_collections_test(TestCase): @@ -46,13 +27,13 @@ def test_KeyedSet(self) -> None: class geometry_test(TestCase): - def test_Cylinder(self) -> int: + def test_Cylinder(self) -> None: cylinder = Cylinder(length=10, diameter=2) assert cylinder.radius() == 1 assert cylinder.volume() == math.pi * 1 ** 2 * 10 - def test_RectangularPrism(self) -> int: + def test_RectangularPrism(self) -> None: prism = RectangularPrism(width=5, thickness=3, length=10) self.assertEqual(prism.cross_section_area(), 15) @@ -117,3 +98,16 @@ def test_evenly_spaced_indices(self) -> None: with self.assertRaises(ValueError): evenly_spaced_indices(total, total + 1, goal='spread') + + def test_unsort(self) -> None: + unsorted_items = [50, 30, 20, 10, 40] + + unsorters, sorted_items = unsort(unsorted_items) + unsorters = list(unsorters) + sorted_items = list(sorted_items) + assert sorted_items == [10, 20, 30, 40, 50] + assert unsorters == [4, 2, 1, 0, 3] + + assert [sorted_items[index] for index in unsorters] == unsorted_items + + assert unsort(()) == ((), ())