Haskell преобразовывает список в список кортежей

у меня есть список как это

["peter","1000","michell","2000","kelly","3000"]

и я хотел бы преобразовать в

[("peter",1000),("michell", 2000),("kelly",3000)]

Помогите.Спасибо.

7
задан Antal Spector-Zabusky 18 June 2010 в 04:03
поделиться

3 ответа

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

Если вы хотите обрабатывать нечетную длину, просто добавьте cnv [x] = вариант перед последним

14
ответ дан 6 December 2019 в 07:05
поделиться

Именно для такой задачи я считаю удобным иметь функцию stride , которая берет каждый n-й элемент из списка:

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

Ее можно использовать для преобразования списка в пары:

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

Пример (обратите внимание, что последний элемент может быть отброшен, если у него нет пары):

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

Его можно даже легко расширить до триплетов или более длинных кортежей:

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

Чтобы выполнить преобразование из String в целое число в вашем примере, вы можете сопоставить функцию read на втором шаге:

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

, что дает:

[("peter",1000),("michell",2000),("kelly",3000)]
3
ответ дан 6 December 2019 в 07:05
поделиться

Единственное решение немного короче, но вот нерекурсивная версия, использующая splitEvery из очень удобной библиотеки split :

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

Шаги здесь несколько понятнее (по крайней мере для меня), чем в рекурсивной версии.

8
ответ дан 6 December 2019 в 07:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: