22 Stimmen

Wie kann man mehrere Listen in Haskell zippen?

In Python zip Funktion akzeptiert eine beliebige Anzahl von Listen und fügt sie zusammen.

>>> l1 = [1,2,3]
>>> l2 = [5,6,7]
>>> l3 = [7,4,8]
>>> zip(l1,l2,l3)
[(1, 5, 7), (2, 6, 4), (3, 7, 8)]
>>> 

Wie kann ich zip mehrere Listen in Haskell zusammenführen?

3voto

ADEpt Punkte 5434

Es ist nicht trivial, aber machbar. Siehe dieser Blogbeitrag . Ich weiß nicht, ob dies in einige Bibliothek gemacht.

Hier ist andere Version , was einfacher ist. Dieser könnte eigentlich hier eingefügt werden:

{-# LANGUAGE MultiParamTypeClasses
           , FunctionalDependencies
           , FlexibleInstances
           , UndecidableInstances
           #-}

-- |
-- Module      :  Data.List.ZipWithN
-- Copyright   :  Copyright (c) 2009 wren ng thornton
-- License     :  BSD3
-- Maintainer  :  wren@community.haskell.org
-- Stability   :  experimental
-- Portability :  non-portable (MPTCs, FunDeps,...)
--
-- Provides a polyvariadic 'map'/'zipWith' like the @map@ in Scheme.
-- For more details on this style of type hackery, see:
--
--    * Chung-chieh Shan, /A polyvariadic function of a non-regular/
--      /type (Int->)^N ([]^N e)->.../
--      <http://okmij.org/ftp/Haskell/polyvariadic.html#polyvartype-fn>
----------------------------------------------------------------
module Data.List.ZipWithN (ZipWithN(), zipWithN) where

-- | This class provides the necessary polymorphism. It is only
-- exported for the sake of giving type signatures.
--
-- Because we can't do functor composition without a lot of noise
-- from newtype wrappers, we use @gr@ and @kr@ to precompose the
-- direct/list functor with the reader functor and the return type.
class ZipWithN a gr kr | kr -> gr a where
    _zipWithN :: [a -> gr] -> [a] -> kr

instance ZipWithN a b [b] where
    _zipWithN = zipWith ($)

instance ZipWithN b gr kr => ZipWithN a (b -> gr) ([b] -> kr) where
    _zipWithN = (_zipWithN .) . zipWith ($)

-- | Polyadic version of 'map'/'zipWith'. The given type signature
-- isn't terribly helpful or intuitive. The /real/ type signature
-- is:
--
-- > zipWithN :: {forall a}^N. ({a->}^N  r) -> ({[a]->}^N  r)
--
-- Note that the @a@ type variables are meta and so are independent
-- from one another, despite being correlated in N across all
-- repetitions.
zipWithN :: (ZipWithN a gr kr) => (a -> gr) -> [a] -> kr
zipWithN = _zipWithN . repeat

Wenn Sie gerade erst anfangen, Haskell zu lernen, verschieben Sie das Verstehen für einige Zeit :)

3voto

ertes Punkte 4352

Die Verallgemeinerung des Reißverschlusses ist eigentlich recht einfach. Man muss nur spezialisierte Versionen der Applicative Kombinatoren für ZipList :

z :: [a -> b] -> [a] -> [b]
z = zipWith ($)

infixl 4 `z`

Jetzt können Sie so viele Listen zippen, wie Sie wollen:

f <$> xs `z` ys `z` zs

oder alternativ:

repeat f `z` xs `z` ys `z` zs

1voto

Thomas Eding Punkte 33018

Wenn alle Ihre Daten vom gleichen Typ sind, können Sie das tun:

import Data.List (transpose)

zipAllWith :: ([a] -> b) -> [[a]] -> [b]
zipAllWith _ []  = []
zipAllWith f xss = map f . transpose $ xss

zipAll = zipAllWith id

Exemple :

> zipAll [[1, 2, 3], [4, 5, 6], [7, 8]]
[[1,4,7],[2,5,8],[3,6]]

1voto

camh Punkte 38167

Für eine bestimmte Anzahl von Listen können Sie etwa so vorgehen:

> let l1 = [1,2,3]
> let l2 = "abc"
> let l3 = [10.0, 11.0, 12.0]
> let l4 = [True, False, False]

> [ (e1,e2,e3,e4) | (((e1,e2),e3),e4) <- zip (zip (zip l1 l2) l3) l4 ]
[(1,'a',10.0,True),(2,'b',11.0,False),(3,'c',12.0,False)]

Es handelt sich nicht um eine allgemeine Funktion, sondern um ein Muster, das Sie auf eine unterschiedliche Anzahl von Listen anwenden können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X