2013-06-03 18 views
7

Chcę utworzyć listę konkatenacji w Haskell. Mam [1,2,3] i [4,5,6] i chcę produkować [14,15,16,24,25,26,34,35,36]. wiem, że mogę używać zipWith lub czegoś, ale jak to zrobić odpowiednik: foreach w first_array foreach w second_arrayRównoważnik pętli zagnieżdżonej

Chyba muszę używać mapę i pół curried funkcje, ale naprawdę nie można zrobić to sam: S

Odpowiedz

17

można użyć listowych to zrobić:

[x * 10 + y | x <- [1..3], y <- [4..6]] 

W rzeczywistości jest to bezpośrednie tłumaczenie z zagnieżdżonej pętli, ponieważ pierwszy jest zewnętrzna index/wolniej, a drugi jest szybszy/wewnętrzny indeks.

12

można wykorzystać fakt, że listy są monady i użyć zrobić notacji:

do 
    a <- [1, 2, 3] 
    b <- [4, 5, 6] 
    return $ a * 10 + b 

Można również wykorzystać fakt, że listy są aplikacyjne funktory (zakładając, że masz Control.Applicative importowane):

(+) <$> (*10) <$> [1,2,3] <*> [4,5,6] 

Zarówno wynik w następujących przypadkach:

[14,15,16,24,25,26,34,35,36] 
5

Jeśli naprawdę lubisz widząc for w kodzie można też zrobić coś takiego:

for :: [a] -> (a -> b) -> [b] 
for = flip map 

nested :: [Integer] 
nested = concat nested_list 
    where nested_list = 
      for [1, 2, 3] (\i -> 
      for [4, 5, 6] (\j -> 
       i * 10 + j 
      ) 
     ) 

Można również zajrzeć do for i Identity bardziej idiomatycznym podejścia.

1

Zagnieżdżone pętle odpowiadają zagnieżdżonym zastosowaniom map lub podobnym funkcjom. Pierwsze przybliżenie:

notThereYet :: [[Integer]] 
notThereYet = map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3] 

To daje zagnieżdżone listy, które można wyeliminować na dwa sposoby. Jednym z nich jest użycie concat :: [[a]] -> [a] funkcję:

solution1 :: [Integer] 
solution1 = concat (map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]) 

Innym jest użycie tej funkcji wbudowanej:

concatMap :: (a -> [b]) -> [a] -> [b] 
concatMap f xs = concat (map f xs) 

Korzystanie że:

solution2 :: [Integer] 
solution2 = concatMap (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3] 

Inni ludzie wymienionych listowych i lista Monada, ale te naprawdę od dołu do zagnieżdżonych zastosowań concatMap.

0

Ogólne rozwiązanie łączenie dwóch list liczb to:

concatInt [] xs = xs 
concatInt xs [] = xs 
concatInt xs ys = [join x y | x <- xs , y <- ys ] 
    where 
    join x y = firstPart + secondPart 
     where 
     firstPart = x * 10^lengthSecondPart 
     lengthSecondPart = 1 + (truncate $ logBase 10 (fromIntegral y)) 
     secondPart = y 

przykład: concatInt [1,2,3], [4,5,6] == [14,15,16 , 24,25,26,34,35,36]

Bardziej złożony przykład: konkatnt [0,2,10,1,100,200] [24,2,999,44,3] == [24,2,999,44, 3,224,22,2999,244,23,1024,102,10999,1044,103,124,12,1999,144, 10024,1002,100999,10044,1003,20024,2002,200999,20044,2003]

1

Ponieważ do notacji i zrozumienie listy zostały już powiedziane. Jedyną inną opcją, którą znam, jest kombinator liftM2 z Control.Monad. Co jest dokładnie tym samym co poprzednie dwa.

liftM2 (\a b -> a * 10 + b) [1..3] [4..6] 
+0

... tylko krótszy (niż wszystkie oprócz pierwszego). :) nicccce! –

Powiązane problemy