2016-11-12 4 views
0

Эй, ребята, у меня есть вопрос о соответствующих спискахсписок Matching списков с другим списком списков

Учитывая список списков:

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

Тогда матч Booleans из списка 1 с другими списками так это происходит:

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

Есть ли какая-либо особая причина, почему это списки списков, учитывая, что в вашем примере все внутренние списки имеют только один элемент? – duplode

+0

тоже облегчают чтение, я думаю, но да, они могут иметь более 1 элемента. – SlippyJoe

+0

. Сделать его проще для чтения - не очень хорошая причина для использования вложенных списков, поскольку он делает все гораздо сложнее, чем необходимо, - вам нужно будет решить что делать с другими элементами. – duplode

ответ

0

Предполагая, что вы измените их в списки, как это было рекомендовано duplode, как о проносясь вместе два списка в списке понимание, что-то вроде этого:

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

где defaultVal должны быть определены, но, кажется, Dead и 0 для списков 2 и 3.

(я не имею доступа прямо сейчас Haskell, поэтому синтаксис не может быть 100%, но это идея.)

2

Насколько я вижу, использование вложенных списков здесь не нужно. Без них все, что вам нужно, это zipWith и соответствующее объединение функции:

-- 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"] 

Две вариации на тему. Во-первых, если зависит ли значение должно быть изменено только на то, что значение, то вы можете просто использовать map/fmap:

-- 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"] 

Во-вторых, вы можете предпочесть использовать Maybe для обозначения мёртвость, а не используя произвольное значение (что, если кого-то на самом деле называют «мертвым»)?

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] 

Вы можете использовать такие функции, как maybe, fromMaybe и catMaybes (последние два в Data.Maybe), чтобы избавиться от Nothing с тем не менее вы чувствуете, как это делать:

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

Вы можете использовать zipWith . zipWith :: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]] для сопоставления списков списков. Например:

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

Следует отметить, что это будет застегивать каждую пару совпадающих внутренних списков, чтобы «убить« мертвых »[[False, True]] [[« James »,« Seamus »]]' будет '[[" Dead " "Симус"]] '. – duplode

+0

Да. Если бы ожидалось иначе, я думаю, что для первого списка было бы странно иметь тип '[[Bool]]' вместо '[Bool]'. – jpath

Смежные вопросы