簡體   English   中英

Haskell中Python Groupby的模擬

[英]Analog of python groupby in haskell

在python中有groupby函數。

它的類型可以用haskell這樣的groupby :: a->b->[a]->[(b, [a])]表示groupby :: a->b->[a]->[(b, [a])]因為它需要對數據進行排序,所以我們可以認為它的運行時間為O(n*log(n))

我可能不是唯一對此不滿意的人,所以我找到了這個 。groupby的實現需要在輸入序列上進行兩次傳遞。 因此,我認為它的運行時間為O(n) ,但是正如文檔中所說的那樣,它並不是很懶惰,因為如果您不向其傳遞密鑰,則需要進行傳遞序列以從中收集所有唯一密鑰。項目。

所以我以雷蒙德·赫特格為例

一定會有更好的辦法!

所以我寫了這個

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)

如果您不熟悉python,則此想法非常簡單。 創建key -> queue of elements可變字典嘗試獲取序列的下一個元素及其鍵值。 如果序列不為空,則根據其鍵將該值添加到組隊列中。 如果我們沒有看到此密鑰產生一對(密鑰,可迭代組),則后一個將從緩沖區或序列中獲取密鑰。 如果我們已經看到此鍵,則不執行任何操作並循環。

如果序列結束,則意味着其所有元素已經放入緩沖區(並且可能已消耗)。 如果緩沖區不為空,我們將對其進行迭代並產生重命名(鍵,可迭代)對。

我已經對其和它的作品進行了單元測試。 而且它確實是懶惰的(意味着在消費者沒有要求之前它不會從序列中獲取任何值),並且它的運行時間應該為O(n)

我試圖對此功能進行haskell模擬,但沒有發現任何東西。

可以在haskell中寫這樣的東西嗎? 如果是這樣,請顯示解決方案,否則請說明原因。

如果我理解正確,則您想要的類型是

(a -> k) -> [a] -> [(k, [a])]

即,給定鍵功能和項目列表,按鍵將項目分組。

在Haskell中,有一個庫函數groupBy可以執行類似的操作。 假定您有一個排序列表,並將滿足布爾條件的項目分組到子列表中。 我們可以用它來做您想要的:

import Data.List
import Data.Ord

groupByKey :: (a -> k) -> [a] -> [(k, [a])]
groupByKey keyF xs = map getResult groups
   where
      keyPairs = map (\v -> (keyF v, v)) xs
      groups = groupBy (\v1 v2 -> fst v1 == fst v2) 
                  $ sortBy (comparing fst) keyPairs
      getResult xs = (fst $ head xs, map snd xs)

keyPairs是參數中每個元素的對(key, value) groups首先使用sortBy分類為鍵順序,然后將結果分組到共享相同鍵的子列表中。 getResult將一個子列表轉換為包含鍵(從head元素獲取)和原始值列表的對。 我們可以安全地使用head因為groupBy永遠不會給出空的子列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM