group :: Ord a => [(a, [b])] -> [(a, [b])]
I want to look up all pairs that have the same fst, and merge them, by appending all the list of bs together where they have the same a and discarding the unnessecary pair and so on…
I got as far as:
group ((s, ls):(s', ls'):ps) =
if s == s'
then group ((s, ls++ls'):ps)
else (s, ls) : group ((s', ls'):ps)
group p = p
but obviously this ain’t going to cut it, because it doesn’t group everything.
Edit:
example
[("a", as),("c", cs), ("c", cs3), ("b", bs),("c", cs2), ("b", bs2)]
would output
[("a", as),("c", cs++cs2++cs3),("b", bs++bs2)]
Two alternative solutions to barkmadley’s answer:
As Tirpen notes in a comment, the best way to attack this problem depends on the number m of distinct first elements in the tuples of the input list. For small values of m barkmadley’s use of
Data.List.partitionis the way to go. For large values however, the algorithm’s complexity of O(n * m) is not so nice. In that case an O(n log n) sort of the input may turn out to be faster. Thus,This yields
[("Dup",["2","3","1","5"]),("Non",["4"])]on barkmadley’s input.Alternatively, we can call in the help of
Data.Map:This will yield
[("Dup",["5","1","2","3"]),("Non",["4"])], which may or may not be an issue. If it is, then there are again two solutions:Reverse the input first using
Data.List.reverse:Prepend (
flip (++)) instead of append ((++)) (Thanks to barkmadley; I like this solution better):Both of these definitions will cause
combineto output[("Dup",["2","3","1","5"]),("Non",["4"])].As a last remark, note that all these definitions of
combinerequire the first element of the tuples in the input list to be instances of classOrd. barkmadley’s implementation only requires these elements to be instances ofEq. Thus there exist inputs which can be handled by his code, but not by mine.