4

タプルのリストでタプルアイテム1によってグループ化されたタプルアイテム2を合計できるようにするフォールドバリアントの1つに渡すことができる演算子はどれですか?

だから、私がリストを持っているとしましょう:

[ ('A', 1) , ('A', 3) , ('B', 4 ) , ('C', 10) , ('C', 1) ]

リストを作成したい:

[ ('A', 4) , ('B', 4) , ('C', 11) ]

これはHaskell化されたテーブルであることがわかるので、ここでのテーブルの実際の表現は重要ではありません。これは、入力データを取得して、興味のある出力を生成するためのアプローチです。私はHaskellの新参者であり、C / C ++ / C#のバックグラウンドを持っています。ここでフォールドの適用を認識するのに十分なチュートリアルを実行しましたが、必要と思われるサブフォールディングを理解できません。

編集:これが他の誰かを助ける場合に備えて、これがグループ、foldl1、およびマップを使用した私の解決策であり、ingoの応答に触発されています:

import qualified Data.List as List

mygroup :: [ (Char,Int) ] -> [ [(Char,Int)] ]
mygroup = List.groupBy (\x y -> fst x == fst y) 

myfold :: [(Char,Int)] -> (Char,Int)
myfold = foldl1 (\x y -> (fst x, snd x + snd y))

mysum :: [(Char,Int)] -> [(Char,Int)]
mysum = map myfold . mygroup

実行時:

*ListSum> mysum [ ('A',1) , ('A',2) , ('B',3) , ('C',4) , ('C',5) ]
[('A',3),('B',3),('C',9)]

mygroupは、等価演算子を提供することにより、グループを作成する方法を示しています。最初のタプルアイテムが同じである場合、2人のメンバーは同じグループに属していると表示されます。

myfoldは、2つのタプルを合計する方法を示しています。リストの最初のタプルをフォールドの初期状態として使用し、各タプルの2番目の項目の合計から結果タプルを構成します。

mysumは、マップを使用してこれら2つの関数を構成します。

現在[(Char、Int)]であるデータのスキーマへの依存を解消できるかどうかを確認するために、もう少し時間を費やす可能性があります。これは、groupBy演算子とfold演算子を提供することを意味し、groupBy、foldl1、およびmapを作成するための演習になる可能性があると思います。私はこれが初めてです。

ポイントフリーでポイントはもらえますか?:)

4

3 に答える 3

4

本当に必要なのは、特定の基準でアイテムをグループ化し、グループを折りたたむことです。

あなたが示した例を実装する最も簡単な方法は、連想マップを使用しData.Mapてアイテムをグループ化することです。

import qualified Data.Map as Map

sumGroups :: [(Char, Int)] -> [(Char, Int)]
sumGroups = Map.assocs . Map.fromListWith (+)

これは、関数fromListWithを使用して同じキーを持つアイテムを結合し、結果のマップを でリストに変換しassocsます。

*Main> sumGroups [ ('A', 1) , ('A', 3) , ('B', 4 ) , ('C', 10) , ('C', 1) ]
[('A',4),('B',4),('C',11)]
于 2012-08-20T13:40:49.433 に答える
2

概念的には、次の 2 つの手順が必要です。

transform [('A', 1) , ('A', 3) , ('B', 4 ) , ('C', 10) , ('C', 1)]
to [('A', [1,3,4]), ('C', [10, 1])]
and further to [('A', 8), ('C', 11)]

役立つ関数: groupBy、using、fst、map、sum

于 2012-08-20T13:55:05.697 に答える