Steven Morad
Steven Morad

Reputation: 2617

Get element of tuple in list

How do I access an element of a tuple in a list?

For example

func :: [(Int, Int, Int)] -> Int
func (x:xs) --here I want to access c of every tuple (a,b,c)

Upvotes: 2

Views: 845

Answers (3)

kosmikus
kosmikus

Reputation: 19637

Note that you can simply nest pattern matches:

func :: [(Int, Int, Int)] -> Int
func ((a, b, c) : xs) = ... -- do something with c, and probably recurse on xs
func []               = ... -- don't forget the base case

Upvotes: 4

ssm
ssm

Reputation: 5373

You may be stuck with conversions. Average with an Int is inherently messy if you use the wrong averaging. You need the fromIntegral command to convert your Int to a float-type number like so ...

f x = sAll / l
    where
        f3 (_,_,x) = x 
        sAll       = sum $ map (fromIntegral . f3) x 
        l          = fromIntegral $ length x 

{- 
[prompt] f [(1,2,3), (2,4,6)]
4.5
[prompt] 
-}

Was this the problem?

Upvotes: 1

bheklilr
bheklilr

Reputation: 54058

You can make a simple function to access the third element of a tuple then just use map

thrd :: (a, b, c) -> c
thrd (a, b, c) = c

func :: [(Int, Int, Int)] -> [Int]
func xs = map thrd xs

That will give you a list containing the third element of each tuple. I don't know what you want to do to it to convert it to a single Int, though. Could you elaborate on your use case?


To get the average of these elements you're going to have to do some conversion. You can't divide Ints, because Int is not an instance of the Fractional type class which defines (/). You could write an average function like

average :: Fractional a => [a] -> a
average xs = sum xs / fromIntegral (length xs)

But this would mean you would have to convert every single element coming out of map thrd xs into a Fractional. It'd be much more efficient to make a specialized averaging function for the Int type defined as

averageInt :: Fractional a => [Int] -> a
averageInt xs = fromIntegral (sum xs) / fromIntegral (length xs)

The difference here is that you sum the list first, then convert that result to a Fractional. You have to perform the sum either way, but this reduces the number of conversion you have to do from the number of elements in your list to 1 no matter the size of the list.

You can then use it as

averageThrd :: Fractional a => [(Int, Int, Int)] -> a
averageThrd xs = averageInt $ map thrd xs

Since Float and Double are both instances of Fractional, you can convert to either of these types on demand with some in-line type annotations:

> averageThrd [(0, 0, 1), (0, 0, 2), (0, 0, 3)] :: Double
2.0
> averageThrd [(0, 0, 1), (0, 0, 2), (0, 0, 3)] :: Float
2.0

Upvotes: 4

Related Questions