Add get_equivalence_class util method
This way, we can partition songs into equivalence classes based on identicalness
This commit is contained in:
parent
8988bb820c
commit
d3d28777e7
4
karaokatalog/util/__init__.py
Normal file
4
karaokatalog/util/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
"""
|
||||||
|
Utility functions completely independent of the root project (i.e., you could copy
|
||||||
|
them to any other code project and they'd immediately work).
|
||||||
|
"""
|
32
karaokatalog/util/get_equivalence_classes.py
Normal file
32
karaokatalog/util/get_equivalence_classes.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from collections.abc import Iterable, Sequence, Callable
|
||||||
|
|
||||||
|
type EquivalenceClass[T] = Sequence[T]
|
||||||
|
|
||||||
|
|
||||||
|
def get_equivalence_classes[T](
|
||||||
|
items: Iterable[T], is_equivalent: Callable[[T, T], bool]
|
||||||
|
) -> Sequence[EquivalenceClass[T]]:
|
||||||
|
"""
|
||||||
|
Partition an iterable of items into equivalence classes under the given equivalence relation.
|
||||||
|
The order of `items` is kept within the equivalence classes.
|
||||||
|
|
||||||
|
>>> from math import floor
|
||||||
|
>>> get_equivalence_classes([1.0, 2.1, 1.1, 1.0, 2.2, 2.1, 3.3], lambda a, b: floor(a) == floor(b))
|
||||||
|
((1.0, 1.1, 1.0), (2.1, 2.2, 2.1), (3.3,))
|
||||||
|
"""
|
||||||
|
equivalence_classes: list[list[T]] = []
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
# Check if the item belongs into an already existing equivalence class
|
||||||
|
for equivalence_class in equivalence_classes:
|
||||||
|
# Pick an arbitrary representative of the equivalence class (we are allowed to do this
|
||||||
|
# because it is an equivalence class)
|
||||||
|
representative = equivalence_class[0]
|
||||||
|
if is_equivalent(item, representative):
|
||||||
|
equivalence_class.append(item)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# This item forms a new equivalence class, so we create one containing only the item and append it
|
||||||
|
equivalence_classes.append([item])
|
||||||
|
|
||||||
|
return tuple(tuple(equivalence_class) for equivalence_class in equivalence_classes)
|
Loading…
x
Reference in New Issue
Block a user