2012-04-16 3 views
0

У меня есть список кортежей внутри другого списка, и у меня проблемы с поиском среднего.Haskell - добавить кортежи в список вместе?

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

Мой список кортежей - [(String, Int)], и я хочу, чтобы можно было найти среднее значение для всех кортежей.

+0

среднее что? ints внутри кортежей? –

+0

Да, простите, я должен был быть более ясным. – JamieB

+0

Вы обеспокоены эффективностью? –

ответ

0

Если вы ищете сеть, вы найдете много функций average :: (Real a, Fractional b) => [a] -> b, e.g. here.

Для этого вам нужна функция типа [(String, Int)] -> [Int], тогда вы можете поместить их вместе.

4

Вы можете легко преобразовать это в список простых целых чисел с map snd. Итак, в основном, sum $ map snd listOfTuples, чтобы добавить их все вместе. (Чтобы эффективно вычислить среднее значение, вы можете сделать что-то более сложное, но это должно поставить вас на правильный путь.)

+2

Этот намек указывает на идиоматический стиль Haskell для решения этой проблемы. Вы также можете решить его (возможно, более эффективно?) С помощью рекурсивной вспомогательной функции или с помощью 'foldl'', но оба эти метода более длинные и, возможно, менее ясные, а также менее идиоматические ... – comingstorm

0

Вот способ расчета суммы и длины за один проход.

Это некрасиво, но это работает.

averageTuples ts = let results = calculateSum ts 
    in (fst results)/(snd results) 

calculateSum ts = foldr acc (0,0) $ zip (map snd ts) (repeat 1) where 
    acc (x, y) (x', y') = (x+x', y+y') 

main = print $ averageTuples [("foo", 1.09), ("bar", 2.6789), ("baz", 3.4)] 

Имейте в виду, что вы, возможно, придется использовать fromIntegral, если у вас есть список всех Ints

1

Кроме того, данный список формы [(String,Int)] вы можете использовать функцию распаковать, которая имеет тип

[(a,b)] -> ([a],[b])

Так, чтобы получить среднее значение списка, который выглядит как [(String, Int)], вы бы просто использовать:

(sum $ snd $ unzip myList)/length(myList)

Вам нужно будет исправить тип, чтобы можно было разделить его с помощью функции fromIntegral.

Таким образом, вы могли бы написать следующую функцию:

average :: [(a,Int)] -> Double

average xs = (fromIntegral $ sum $ snd $ unzip xs)/(fromIntegral $ length xs)

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