Reputation:
I am trying to build a list of tuples. Input is a list of tuples [([char], int1, int2), ...]
and the output is the list of tuples such that [([char], int1, int2, (int1/int2)), ...]
. I know that this code below is wrong because I think it is building a list of lists of tuples [[(),(),(),()], [(),(),(),()]]
.
Code:
{- take a list of labels, values, and weights and return list of labels and fractions -}
fraclist [] = []
fraclist x = [ (y,r,q,z) : y <- first (head x) | r <- scnd (head x) | q <- last (head x) | z <- r/q ] : fraclist tail x
{- helper func to get values from tuples -}
frst (a,b,c) = a
scnd (a,b,c) = b
last (a,b,c) = c
How might I get the proper output form as described? Also, how might I output the list of tuples ordered such that the z's are in descending order?
Upvotes: 0
Views: 3420
Reputation: 800
Here is a simple solution without list comprehension:
import Data.List
-- (string, int1, int2) -> (string int1, int2, (int1/int2))
fraclist list = map generateTuple list
where generateTuple (label, value, weight) = (label, value, weight, (value)/(weight))
sortFracListByValueWeightRatio list = sortBy sorter list
where sorter (_,_,_,d) (_,_,_,h) = if d > h then GT else LT
testList = [("first",3.0,4.0), ("second",4.0,7.0)]
Nothing fancy (I've only used haskell a week).
fraclist works by mapping the generateTuple function to the list. The generateTuple function simply returns a tuple of form (title, value, weight, value/weight). Map is a built in function which simply applies a given function to each element of the list.
The sortFracListByValueWeightRatio (sorry for the long name) uses the built in sortBy function (comes from Data.List), which sorts a given list using a custom function for comparing items. Sorter is my item comparer, and it simply compares the value/weight ratios and returns either GT or LT (Greater Than / Lower Than). Hence, the list items are compared using the custom comparer, and sorted based on its answer.
A significant improvement of readability would probably be to use types to describe the values instead of just tuples. Also I'm using doubles in the test list, but that is easy to change.
Upvotes: 0
Reputation: 183978
I think you want just
fraclist xs = [(y,r,q, r `quot` q) | (y,r,q) <- xs]
(Note: I used quot
instead of (/)
since you named the components int1
, int2
.)
A variant not using list comprehensions is
fraclist = map (\(y,r,q) -> (y,r,q, r `quot` q))
Your code doesn't compile, in such cases it is better to post the error message so people can see at one glance what the probable cause is.
You get a parse erro on the first <-
in
fraclist x = [ (y,r,q,z) : y <- first (head x) | r <- scnd (head x) | q <- last (head x) | z <- r/q ] : fraclist tail x
because the expression (y,r,q,z) : y <- first (head x)
before the first |
separating the generated expressions from the generator expressions isn't well-formed. I think it's just a typo and you meant to use |
instead of (:)
there too.
Then you have several |
separators in your list comprehension, which is not valid without the ParallelListComp
extension. However, the code doesn't look like a parallel list comprehension is really what you attempt here, since all three values are drawn from the same list. Finally, the last part | z <- r/q
is again not well-formed, since r/q
is not a list from which elements can be drawn in a list comprehension. You probably intended let z = r/q
there.
Upvotes: 1
Reputation: 49115
This code doesn't compile (syntax errors), but after fixing that (I'd recommend reading up on the syntax of list comprehensions (','s vs. '|'s)) and making some other changes:
used a list comprehension, which takes care of the base case and the mapping over the list -- so I was able to eliminate fraclist [] = []
and the head
/tail
/:
business
used pattern matching to pull the values out of the input tuples -- this is often much easier to read than using functions to take apart values
added an explicit type signature for documentation purposes
here's what I think you meant:
fraclist :: (Integral t1) => [(t, t1, t1)] -> [(t, t1, t1, t1)]
fraclist xs = [(x, y, z, div y z) | (x, y, z) <- xs]
I'll leave the sorting to you.
Upvotes: 1