30

n個の要素のグループを作成するライブラリ内のリストに対する操作はありますか?例:n = 3

groupInto 3 [1,2,3,4,5,6,7,8,9] = [[1,2,3],[4,5,6],[7,8,9]]

そうでない場合、どうすればよいですか?

4

4 に答える 4

55

Hoogleをすばやく検索すると、そのような機能はないことがわかりました。一方、splitパッケージには、と呼ばれるものがあるとの回答がありましたchunksOf

ただし、自分で行うことはできます

group :: Int -> [a] -> [[a]]
group _ [] = []
group n l
  | n > 0 = (take n l) : (group n (drop n l))
  | otherwise = error "Negative or zero n"

もちろん、いくつかの括弧は削除できます。コードの機能を理解するために、ここに残しました。

基本的なケースは単純です。リストが空の場合は常に、空のリストを返すだけです。

nが正の場合、再帰的なケースが最初にテストされます。nis以下の場合0、無限ループに入りますが、それは望ましくありません。take次に、and drop:を使用してリストを2つの部分に分割しtake、最初のn要素をdrop返し、他の要素を返します。次に、n元のリストの他の要素に関数を適用して取得したリストに最初の要素を追加します。

ここに画像の説明を入力してください

于 2012-10-13T19:53:50.620 に答える
37

この関数は、他の同様の関数の中でも、人気のある分割パッケージに含まれています。

> import Data.List.Split
> chunksOf 3 [1,2,3,4,5,6,7,8,9]
[[1,2,3],[4,5,6],[7,8,9]]
于 2012-10-13T20:02:25.613 に答える
18

ミハイが指摘したように、自分で書くことができます。ただし、 -の組み合わせsplitAtのように入力リストに2つのパスを必要としないため、この関数を使用します。takedrop

chunks :: Int -> [a] -> [[a]]
chunks _ [] = []
chunks n xs =
    let (ys, zs) = splitAt n xs
    in  ys : chunks n zs

これは一般的なパターンです。反復を繰り返すことにより、シード値(この場合は入力リスト)からリストを生成します。このパターンはunfoldr関数に取り込まれます。少し変更したバージョンで使用できます(より簡潔なバージョンを提供してくれたWill NesssplitAtに感謝します)。

chunks n = takeWhile (not . null) . unfoldr (Just . splitAt n)

つまり、要素unfoldrのチャンクを生成するnと同時に、入力リストをn要素ごとに短縮し、空のリストを取得するまでこれらのチャンクを生成します。この時点で、最初の入力は完全に消費されます。

もちろん、他の人が指摘しているように、モジュールの既存の関数を使用する必要がありsplitます。しかし、標準のHaskellライブラリのリスト処理機能に慣れることは常に良いことです。

于 2012-10-14T13:15:35.040 に答える
7

これはしばしば「チャンク」と呼ばれ、にない最も頻繁に言及されるリスト操作の1つですbase。パッケージsplitはそのような操作を提供しますが、ハドックのドキュメントをコピーして貼り付けます。

 > chunksOf 3 ['a'..'z']
 ["abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"]

+PKG_NAMEさらに、私の希望に反して、hoogleはライブラリの小さなセット(GHCまたはおそらくHPで提供されるもの)のみを検索しますが、 -hoogle withを使用して、検索にパッケージを明示的に追加できますInt -> [a] -> [[a]] +split。このため、ハヨを使う人もいます。

于 2012-10-13T20:04:38.527 に答える