В python есть функция groupby.Аналог группы python в haskell
Это тип может быть выражен в haskell следующим образом: groupby :: a->b->[a]->[(b, [a])]
Потому что для этого нужны данные для сортировки, мы можем думать о его рабочем времени как O(n*log(n))
.
Я, вероятно, был не единственным, кто был недоволен этим, поэтому я нашел это library Эта реализация groupby требует двух проходов над входной последовательностью. Поэтому я думаю, что его время работы - O(n)
, но, как говорится в документах, это не очень лениво, потому что если вы не передадите ему ключи, ему необходимо будет пройти последовательность, чтобы собрать все уникальные ключи из элементов.
Так что я подумал, ссылаясь на Raymond Hetttinger
Там должно быть лучше!
Так что я написал это
from collections import defaultdict, deque
def groupby(sequence, key=lambda x: x):
buffers = defaultdict(deque)
kvs = ((key(item), item) for item in sequence)
seen_keys = set()
def subseq(k):
while True:
buffered = buffers[k]
if buffered:
yield buffered.popleft()
else:
next_key, value = next(kvs)
buffers[next_key].append(value)
while True:
try:
k, value = next(kvs)
except StopIteration:
for bk, group in buffers.items():
if group and bk not in seen_keys:
yield (bk, group)
raise StopIteration()
else:
buffers[k].append(value)
if k not in seen_keys:
seen_keys.add(k)
yield k, subseq(k)
В случае, если вы не знакомы с питоном идея очень проста. Создать изменяемый словарь key -> queue of elements
Попробуйте взять следующий элемент последовательности и его значение ключа. Если последовательность не пуста, добавьте это значение в очередь групп в соответствии с его ключом. Если мы не увидели, что этот ключ дает пару (ключевая, итерируемая группа), последняя будет принимать ключи либо из буфера, либо из последовательности. Если мы уже видели это, этот ключ больше ничего не делает и цикл.
Если последовательность завершена, это означает, что все ее элементы уже либо помещены в буферы (и, возможно, потреблены). Если буферы не пусты, мы перебираем их и получаем пары переименования (ключевые, итерируемые).
Я уже тестировал его и его работы. И это действительно лениво (это означает, что это не будет иметь никакого значения от последовательности, пока потребитель не попросит об этом), и это время работы должно быть O(n)
.
Я пробовал использовать haskell аналог этой функции и не нашел.
Можно ли написать такую вещь в haskell? Если да, пожалуйста, покажите решение, если нет, то объясните, почему.
http://hackage.haskell.org/package/discrimination-0.2.1/docs/Data-Discrimination.html#v:groupWith – leftaroundabout
@leftaroundabout Да, это в основном то же самое, но тип 'a-> б -> [[а]] '. Как я узнаю, какой класс эквивалентности есть? Видите ли, я искал hoogle для типа 'a-> b -> [(b, [a])]' – user1685095
@leftaroundabout. С другой стороны, я мог бы, вероятно, попытаться прочитать источники и понять, как их изменить что он вернет имена классов эквивалентности. Я просматривал источники, судя по импорту, он использует изменчивое состояние, верно? Считаете ли вы, что это возможно без изменчивого состояния? – user1685095