2014-11-21 3 views
1

Я следующий список в HaskellКак извлечь кортежи из списка списков в Haskell

[ 
    [("Name", "Alice"), ("Age", "21")], 
    [("Name", "Bob"), ("Age", "22")], 
    [("Name", "Eve"), ("Age", "20")] 
] 

Как я могу получить список [...] Веков, как это:

[("Age", "21"), ("Age", "22"), ("Age", "20")]

Я думаю, что это можно сделать, используя множество понятий, но я не уверен.

+0

Если вы хотите извлечь кортежи из этого конкретного списка, у вас есть ответ. Если вам нужно работать с общими списками, укажите общие требования. Вы хотите получить вторую запись из каждого списка или записи, в которых есть «Возраст», или что-то еще. –

+0

@Franky да, вы правы, я изменил '(String, Int)' to '(String, String)' – Krimson

+2

Вы ищете что-то более сложное, чем 'map (!! 1)'? –

ответ

3

Ну, я дам вам ответ, но первый, обратите внимание, что тип списка, который вы предоставили нам не разрешено ....

Первый тип в каждом списке имеет тип (String, String), второй имеет тип Num a=>(String, a). Haskell не разрешает смешанные списки.

Это, как говорится, как только вы это исправить (например, изменение возрастного кортежа ("age", "2")), у вас есть несколько вариантов:


Если вы хотите всегда значение в кортеже, начиная с «Age "можно использовать следующую

map (lookup "Age") $ theList 

Это почти работает, но будет возвращать тип [Maybe String]. Вы можете удалить Just с помощью fromJust, но будьте осторожны, это приведет к сбою программы, если она не существует. Более чистым подходом было бы использовать fromMaybe, что позволит вам заполнить значение по умолчанию в случае Nothing.

map (fromMaybe "ageless" . lookup "Age") $ theList 

Если вы хотите всегда второе значение в списке, используйте

map (snd . tail) $ theList 

Кроме того, программа будет вылетать, если какой-либо список не имеет двух элементов.

В «безопасном» пакете имеются безопасные версии tail (https://hackage.haskell.org/package/safe-0.3.3/docs/Safe.html). Например, вы можете использовать

map (snd . tailDef ("", "Ageless")) $ theList 
0

самый хороший способ, которым я могу думать, делать это будет так:

getAges :: [[a]] -> [a] 
getAges = map (!! 1) 

Это просто функция, которая возвращает второй элемент каждого подсписка в первом списке. Это должно работать в данном конкретном случае, но если вы хотите, чтобы соответствовать кортежи с тегом «Name», что сложнее:

getAges :: [[a]] -> [a] 
getAges list = do 
     person <- list 
     tags <- person 
     get' tags 
    where get' (tag,val) | tag == "Age" = return (tag,val) 
         | otherwise = fail "Not age tag" 

Это извлечет «Возраст» кортежи из вложенного массива, без прикосновений от Maybe!

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