20

Scala には、groupByリスト アイテムからキーを抽出するための関数を受け入れるリストの関数があり、アイテムがキーとそのキーを生成するアイテムのリストから構成されるタプルである別のリストを返します。つまり、次のようなものです。

List(1,2,3,4,5,6,7,8,9).groupBy(_ % 2)
// List((0, List(2,4,6,8)), (1, List(1,3,5,7,9)))

(実際には、現在のバージョンではMap代わりに を提供しているように見えますが、それは重要ではありません)。C# には、値を同時にマップできるさらに便利なバージョンがあります (たとえば、キー関数がタプルの一部を抽出するだけの場合に非常に便利です)。

Haskell には がありますがgroupBy、多少異なります。比較関数に従って実行をグループ化します。

書きに行く前にgroupBy、Haskell に Scala に相当するものはありますか? Hoogle は、署名がどのように見えると私が期待するか (以下) については何も持っていませんが、単に間違っている可能性があります。

Eq b => (a -> b) -> [a] -> [(b,[a])]
4

7 に答える 7

16

関数はかなり簡単に自分で作成できますが、効率的なソリューションが必要な場合は、分類子関数の結果にOrdorHashable制約を配置する必要があります。例:

import Control.Arrow ((&&&))
import Data.List
import Data.Function

myGroupBy :: (Ord b) => (a -> b) -> [a] -> [(b, [a])]
myGroupBy f = map (f . head &&& id)
                   . groupBy ((==) `on` f)
                   . sortBy (compare `on` f)

> myGroupBy (`mod` 2) [1..9]
[(0,[2,4,6,8]),(1,[1,3,5,7,9])]      

Data.HashMap.Strict予想される線形時間のソートの代わりに、ハッシュ マップのようなものを使用することもできます。

于 2013-03-14T14:36:33.043 に答える
3

具体的には、以下が機能するはずです。

scalaGroupBy f = groupBy ((==) `on` f) . sortBy (comparing f)

これでは各グループの結果が得られないというモジュロですfが、本当に必要な場合はいつでも後処理できます

map (\xs -> (f (head xs), xs)) . scalaGroupBy f
于 2013-03-14T15:40:40.440 に答える
2

これは List ライブラリの関数ではありません。

sortBy と groupBy の合成として書けます。

于 2013-03-14T14:39:36.780 に答える
0

このソリューションは、ソートされているかどうかに関係なく、(fx) で壊れてグループ化されます

f = (`mod` (2::Int))

list = [1,3,4,6,8,9] :: [Int]


myGroupBy :: Eq t => (b -> t) -> [b] -> [(t, [b])]

myGroupBy f (z:zs) = reverse $ foldl (g f) [(f z,[z])] zs
  where
    -- folding function                        
    g f ((tx, xs):previous) y = if (tx == ty)
                           then (tx, y:xs):previous
                           else (ty, [y]):(tx, reverse xs):previous
        where ty = f y                        

main = print $ myGroupBy f list

結果: [(1,[1,3]),(0,[4,6,8]),(1,[9])]

于 2013-03-27T10:03:40.653 に答える
0

atracef入れると、@Niklas ソリューションでfは、長さ 2 以上のリストの各要素に対して 3 回評価されることがわかります。f各要素に一度だけ適用されるように、自由に変更しました。fただし、タプルを作成および破棄するコストが、複数回評価するコストよりも低いかどうかは明らかではありません(f任意である可能性があるため)。

import Control.Arrow ((&&&))
import Data.List
import Data.Function

myGroupBy' :: (Ord b) => (a -> b) -> [a] -> [(b, [a])]
myGroupBy' f = map (fst . head &&& map snd)
                   . groupBy ((==) `on` fst)
                   . sortBy (compare `on` fst)
                   . map (f &&& id)
于 2013-03-15T15:29:58.407 に答える
0

Scalaは順序付けを必要としないgroupByimmutable を返すため、対応する Haskell 実装も aを返す必要があります。HashMapHashMap

import qualified Data.HashMap.Strict as M

scalaGroupBy :: (Eq k, Hashable k) => (v -> k) -> [v] -> M.HashMap k [v]
scalaGroupBy f l = M.fromListWith (++) [ (f a, [a]) | a <- l]
于 2020-10-05T08:13:31.430 に答える