My homework task is to group two tuples in a list if the second element of the first tuple is the same as the first element of the second tuple. Then, if the first tuple is (a, b)
and the second is (b, c)
, the tuple (a, c)
must be added to the result list.
I wrote first function wich takes element with one tuple and second list with many tuples and compare each to each.
this one works correcly:
c1 = ("a","x")
d1 = [ ("x","b"), ("z","c"), ("x","b"), ("z","c")
, ("x","b"), ("z","c"), ("x","b"), ("z","c") ]
getByOne c1 a1 = filter (/=[])
[ if (fst (last(take n a1))) == (snd c1)
then [((fst c1), (snd (last(take n a1))))]
else [] | n <- [1..(length a1) ] ]
output:
[ [("a","b")], [("a","b")], [("a","b")], [("a","b")] ]
But the problems is that I can't throw in if then and else statement just simple tuple, so I create a new list. In the end of this "workaround" i am getting list in list in list and so on. Also if output list was bigger, there were be more lists in lists.
Is there any way to pass out only tuple or empty tuple or i should somehow group theses lists ?
You can flatten the result using
concat :: [[a]] -> [a]
then you don't even need to filter (/=[])
- by the way, the condition (/= [])
is more idiomatically written not . null
, since the null
test doesn't impose an Eq
constraint on its argument (you already have one here, so it's just a matter of idiom).
Further, last (take n a1)
is just the n
-th element of a1
if 1 <= n <= length a1
. Since you have that restriction imposed, that can more succinctly be expressed as a1 !! (n-1)
Then you have structurally
getByOne c1 a1 = concat $ [something c1 (a1 !! i) | i <- [0 .. length a1 - 1]]
(I have shifted indices to index by i
), which is clearer and more efficiently expressed as
getByOne c1 a1 = concat $ map (something c1) a1
If you prefer a list comprehension to map
, you can also write that as
getByOne c1 a1 = concat [something c1 x | x <- a1]
which in your case, using the ability to pattern-match in alist-comprehension generator, gives us
getByOne (f,s) a1 = concat [ if a == s then [(f,b)] else [] | (a,b) <- a1]
which is much shorter and more readable. Instead of using if condition then [element] else []
and concat
, even nicer is to use a condition in the list comprehension,
getByOne (f,s) list = [(f,b) | (a,b) <- list, a == s]
which is short and clear.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With