2016-11-12 10 views
0

Hey Leute, ich habe eine Frage zu AbgleichungslistenMatching Liste von Listen mit anderen Liste von Listen

die Liste der Listen Gegeben:

Input List 1 = [[True],[False],[True],[[False]] 
Input List 2 = [[Bob],[Rick],[Lee],[Bill]] 
Input List 3 = [[1],[2],[3],[4]] 

dann die Boolesche 1 von Liste übereinstimmen mit den anderen Listen so dies geschieht:

Input List 1 + Input List 2 = [[Bob],[Dead],[Lee],[Dead]] 
Input List 1 + Input List 2 = [[1],[0],[3],[0]] 
+0

Gibt es einen bestimmten Grund, warum dies Listen von Listen sind, da in Ihrem Beispiel alle inneren Listen nur ein Element haben? – duplode

+0

zu erleichtern es zu lesen, ich denke, aber yeah sie können mehr als 1 Element haben – SlippyJoe

+0

Das Lesen zu erleichtern ist kein guter Grund für die Verwendung verschachtelter Listen, da es alles viel komplizierter als nötig macht - Sie müssten entscheiden was mit den anderen Elementen zu tun ist. – duplode

Antwort

0

Angenommen, Sie sie auf Listen ändern, wie duplode empfohlen, wie etwa innerhalb einer Liste Verständnis, so etwas wie dies zusammen die beiden Listen zu zippen:

[if flag then val else defaultVal | (flag, val) <- zip(list1, list2)] 

wo defaultVal würde angegeben werden müssen, aber scheint Dead und 0 für Listen 2 und 3

(I Zugang nicht sein müssen, gerade jetzt zu Haskell, so dass die Syntax nicht sein kann 100% dort, aber das ist die Idee.)

2

Soweit ich sehen kann, ist die Verwendung verschachtelter Listen hier unnötig. Ohne sie alles, was Sie brauchen, ist zipWith und eine geeignete Kombination von Funktion:

-- The first argument is the "dead" value. Note that this works with any type. 
makeDead :: a -> Bool -> a -> a 
makeDead dead b val 
    | b = val 
    | otherwise = dead 
GHCi> :t zipWith 
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 
GHCi> zipWith (makeDead "Dead") [True,False,True,False] ["Bob","Rick","Lee","Bill"] 
["Bob","Dead","Lee","Dead"] 

Zwei Variationen über das Thema. Erstens, wenn, ob ein Wert geändert wird nur der Wert ist auf das, was abhängig sein sollte, dann können Sie einfach map/fmap verwenden:

-- Affects all names with 'i' as the second letter: 
lethalLetter :: String -> String 
lethalLetter name -> case name of 
    (_:'i':_) -> "Dead" 
    _ -> name 
GHCi> fmap lethalLetter ["Bob", "Rick", "Lee", "Bill"] 
["Bob","Dead","Lee","Dead"] 

Zweitens, könnten Sie mit Maybe bevorzugen Leblosigkeit, um anzuzeigen, anstatt einen beliebigen Wert verwenden (was ist, wenn jemand tatsächlich "Dead" genannt wird)?

makeDead' :: Bool -> a -> Maybe a 
makeDead' b val 
    | b = Just val 
    | otherwise = Nothing 
GHCi> zipWith makeDead' [True,False,True,False] ["Bob","Rick","Lee","Bill"] 
[Just "Bob",Nothing,Just "Lee",Nothing] 

können Sie dann Funktionen wie maybe, fromMaybe und catMaybes (die beiden letzteren sind in Data.Maybe) der Nothing s loszuwerden, aber Sie wie es zu tun fühlen:

GHCi> import Data.Maybe 
GHCi> foo = zipWith makeDead' [True,False,True,False] ["Bob","Rick","Lee","Bill"] 
GHCi> catMaybes foo 
["Bob","Lee"] 
0

Sie können zipWith . zipWith :: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]] für Listenlisten verwenden. Zum Beispiel:

import Data.Bool (bool) 
kill deadVal = zipWith . zipWith $ bool (const deadVal) id 

example = kill 0 [[True, False],[False,True]] [[1,2,3],[2]] 
-- example = [[1,0],[0]] 
+0

Es sollte erwähnt werden, dass dies jedes Paar passender innerer Listen zippen wird, so dass 'kill" Dead "[[False, True]] [[" James "," Seamus "]]' '[[" Dead "sein wird "Seamus"]]]. – duplode

+0

Ja. Wenn man es anders erwarten würde, wäre es seltsam, wenn die erste Liste vom Typ "[[Bool]]" statt "[Bool]" wäre. – jpath