2010-06-18 22 views

Odpowiedz

13
cnv :: [String] -> [(String, Integer)] 
cnv [] = [] 
cnv (k:v:t) = (k, read v) : cnv t 

Jeśli chcesz obsługiwać nieparzystej długości wystarczy dodać cnv [x] = wariant przed ostatnią

+1

Czy możesz wyjaśnić ten wiersz kodu cnv (k: v: t) = (k, czytaj v): cnv t? AFAIK, k v t jest parametrem z listy k jest głową, a v jest ogonem, a cnv t jest kolejnym elementem jako k. Czy moje zrozumienie jest poprawne, ponieważ previosuly mam taką funkcję. nawrócony :: [String] -> \t [(String, Integer)] convert [] = [] konwersji (x: y: xs) = (x, y) konwertować xs i dlaczego kiedy dodać: xs to nie działa? Czy k v t reprezentuje pojedynczy element na liście lub całej liście? – peterwkc

+3

Niezupełnie: w 'k: v: t',' k' to głowa, a 'v: t' to ogon. Tak więc, 'k: v: t' umieszcza pierwsze dwa elementy listy na" k "i" v ", a pozostałe w" t ". Twój kod ma dwa oczywiste problemy: (a) '(x, y)' ma typ '(String, String)', a nie '(String, Integer)'; i (b) nie ma dwukropka przed 'convert xs'. (Nie możesz po prostu zrobić ': xs', ponieważ potrzebujesz' [(String, Integer)] 'ale' xs' ma typ '[String]'.) Ponadto, końcówka formatująca: linie wcięcia z czterema pustymi polami do pobierz bloki kodu (lub wybierz swój kod i kliknij przycisk "101010"), a fragmenty kodu otaczają fragmenty kodu zwrotnego (\ '... kod ... \'). –

+0

(x: xs) Oznacza to, że x to głowa, a pozostały element to ogon dla xs. Dziękuję za wyjaśnienia. – peterwkc

8

ony's solution jest nieco krótszy, ale tu jest nierekursywnych wersja użyciu splitEvery z bardzo poręcznym split library:

cnv = map (\[name, amount] -> (name, read amount :: Int)) . splitEvery 2 

Kroki tutaj są nieco jaśniejsze (przynajmniej dla mnie) niż w wersji rekursywnej.

+2

To zdecydowanie bardziej naturalne. Podzielona biblioteka nie ma dość miłości. Szkoda, ponieważ jest niesamowicie przydatny. –

+0

Zauważ, że 'splitEvery' wydaje się teraz przestarzałe; zamiast tego użyj ['chunksOf'] (https://hackage.haskell.org/package/split-0.2.2/docs/Data-List-Split.html#v:chunksOf). – sevko

3

Dokładnie za zadanie tak uważam, że to wygodne mieć stride funkcję wziąć każdy n-ty element z listy:

stride _ [] = [] 
stride n (x:xs) = x : stride n (drop (n-1) xs) 

To może być użyty do konwersji listę par:

toPairs xs = zip (stride 2 xs) (stride 2 (drop 1 xs)) 

przykładem (należy pamiętać, że ostatni element może być wyrzucone jeśli nie posiada parę):

ghci> stride 2 [1..5] 
[1,3,5] 
ghci> toPairs [1..7] 
[(1,2),(3,4),(5,6)] 

To może być nawet łatwo rozszerzyć do trojaczków lub dłuższych krotek:

toTriplets xs = zip3 as bs cs 
    where as = stride 3 xs 
     bs = stride 3 $ drop 1 xs 
     cs = stride 3 $ drop 2 xs 

Aby wykonać konwersję z String do liczby całkowitej w przykładzie, można mapować read funkcję nad drugim kroku:

let lst = ["peter","1000","michell","2000","kelly","3000"] in 
zip (stride 2 lst) (map read . stride 2 . drop 1 $ lst) :: [(String,Int)] 

który daje: