Haskell перебирает список - PullRequest
       7

Haskell перебирает список

3 голосов
/ 27 сентября 2011

Я знаю, что вы предполагаете, что в Haskell мыслите иначе, но может кто-нибудь дать мне быстрый ответ о том, как перебрать список или вложенный список и распечатать символ, основанный на значении элемента списка.

list1 = [[1 0 0][0 1 0][0 0 1]]

Перебирая этот вложенный список, он должен распечатать x для 0 и y для 1

yxx
xyx
xxy

Спасибо

Ответы [ 7 ]

15 голосов
/ 27 сентября 2011

Прежде всего, я думаю, что вы имеете в виду:

list1 :: [[Int]]
list1 = [[1,0,0],[0,1,0],[0,0,1]]

Что касается того, что вы хотите:

valueOf :: Int -> Char
valueOf 0 = 'x'
valueOf 1 = 'y'
valueOf _ = 'z'

listValues :: [[Int]] -> [String]
listValues = map (map valueOf)

printValues :: [[Int]] -> IO ()
printValues = putStrLn . unlines . listValues

А потом в ghci:

*Main> printValues list1 
yxx
xyx
xxy
3 голосов
/ 27 сентября 2011

Попробуйте:

fun :: [[Int]] -> [String]
fun = (map . map) (\x -> if x == 0 then 'x' else 'y')

Если вам действительно нужна печать результата:

printSomeFancyList :: [[Int]] -> IO ()
printSomeFancyList = putStrLn . unlines . fun
2 голосов
/ 27 сентября 2011

определяет f чем-то вроде

f x = if x == 0 then 'x' else 'y'

тогда

map (map f) [[1,0,0],[0,1,0],[0,0,1]]

- это то, что вы хотите, или если вы хотите, чтобы это было:

map' = map.map
map' f [[1,0,0],[0,1,0],[0,0,1]]
1 голос
/ 27 сентября 2011

Решения, использующие map, являются предпочтительным стилем Haskell. Но пока вы учитесь, вам может быть проще следовать явной рекурсии. Вот так:

charSub :: Int -> Char
charSub 0 = 'x'
charSub 1 = 'y'
charSub x = error "Non-binary value!"

listSub :: [Int] -> String
listSub [] = []
listSub (x:xs) = (charSub x) : (listSub xs)

nestedSub :: [[Int]] -> String
nestedSub [] = []
nestedSub (y:ys) = (listSub y) ++ "\n" ++ (nestedSub ys) 

map делает почти то же самое - он применяет функцию к каждому элементу в списке. Но может быть легче увидеть, что здесь происходит.

1 голос
/ 27 сентября 2011
iterateList = foldl1 (>>).concat.intersperse [putStrLn ""].(map.map) (\c ->  putStr $ if (c==0) then "X" else "Y")
0 голосов
/ 19 апреля 2014

Решения

cambiar = putStr.unlines.(map (map f)) where f x = if x == 0 then 'x' else 'y'
0 голосов
/ 27 сентября 2011

Если вас интересуют произвольные вложенные списки, вы можете написать что-то вроде этого (произвольный вложенный список по сути является деревом):

data Nested a = Leaf a | Nest [Nested a] deriving Show

traverse :: Nested Integer -> Nested Char
traverse (Leaf x) = Leaf (valueOf x)
traverse (Nest xs) = Nest (map traverse xs)

valueOf :: Integer -> Char
valueOf 0 = 'x'
valueOf 1 = 'y'
valueOf _ = 'z'

С этим вы можете сделать:

Main> let nl = Nest [Leaf 1, Leaf 0, Nest [Leaf 0, Leaf 0, Leaf 1, Nest [Leaf 1, Leaf 1, Leaf 0]], Nest [Leaf 1, Leaf 1]]
Main> traverse nl
Nest [Leaf 'y',Leaf 'x',Nest [Leaf 'x',Leaf 'x',Leaf 'y',Nest [Leaf 'y',Leaf 'y',Leaf 'x']],Nest [Leaf 'y',Leaf 'y']]

Функция traverse принимает произвольный вложенный список Integer с и возвращает соответствующий вложенный список Char с в соответствии с valueOf правилом

...