Counting unique elements in a list - list

Is there a straight-forward combination of standard higher-order functions to count the unique elements in a list?
For example the result for
[1, 1, 4, 0, 4, 4]
would be something like
[(1,2), (4,3), (0,1)]

Using Data.Map and tuple sections:
count = Map.fromListWith (+) . map (, 1)
(Add Map.toList if you need a list.)

If order is not important this works:
map (\xs#(x:_) -> (x, length xs)) . group . sort
group . sort will give you a list of lists where all elements that are equal to each other are grouped into the same sublist (without sort, only consecutive equal elements would be grouped together). The map then turns each sublist into a (element, lengthOfSublist)-tuple.
If you want to order the result by first occurrence, you can use zip before the sort to add an index to each element, then, after grouping, sort again by that index and then remove the index.

The simplest thing would be to sort the items into order, use "group" to put them into sub-lists of equal elements, and then count the items in each sub-list.
map (\xs -> (head xs, length xs)) . group . sort

If the list contains only integers, you could also use
import qualified Data.IntMap as I
countElems1 :: [Int] -> [(Int, Int)]
countElems1 = I.toList . foldr (\k -> I.insertWith (+) k 1) I.empty
(Remember to compile with optimization though, otherwise this will be 2x slower than the group . sort method. With -O2 it is slightly faster by 14%.)
You could also use one of the multiset packages which makes the function as simple as
import qualified Math.Combinatorics.Multiset as S
countElems4 = S.toCounts . S.fromList
but being less efficient.
All of the above solutions ignore the original order.

What your talking about is just run length encoding on sorted data: the free online book Real World Haskell has a great example of this. You will want to sort the list before you put it through the runLengthEncoder.

Related

Problem with a list in the form of [(key, [..]) ; ...]

I'm trying to learn OCaml since I'm new to the language and I stumbled across this problem where I can't seem to find a way to see, in a function where I need to merge 2 kinds of these lists, if there is already an element with a key, and if so how to join the elements that come after. Would appreciate any guidance.
For example if I have:
l1: [(k, [e]); (ka, [])]
l2: [(k, [f; g])]
How can I end up with:
fl: [(k, [e; f; g]); (ka, [])]
Basically, how can I filter the key k from both lists while making their elements combine.
There are functions in the standard OCaml library for dealing with lists of pairs where the first element of each pair is a key. You will find them described here: https://ocaml.org/releases/4.12/api/List.html under Association lists.
I will repeat what #ivg says. This is not how you want to solve your problem if you have more than just a few pairs to work with.
First of all, using lists as mappings is a bad idea. It is much better to use dedicated data structures such as maps and hash tables.
Answering your question directly, you can concatenate two lists using the (#) operator, e.g.,
# [1;2;3] # [4;5;6];;
- : int list = [1; 2; 3; 4; 5; 6]
If you don't want repetitive elements when you merge then, and I feel like I repeat myself, it is bad to use lists for sets, it is better to use dedicated data structures such as sets and hash sets. But if you want to continue, then you can merge two lists without repetitions by checking if an element is already in the list before prepending to it. Easy to implement but hard to run, in a sense that it takes quadratic time to merge two lists this way.
If you still want to stick with the list of pairs, then you will find that the List.assoc function is useful, as it finds a value by key. The overall algorithm would be, given two lists, xs and ys, fold over elements of ys using xs as the initial value acc, and for each (ky,y) in ys if ky is already in acc, find the associated with ky value x and remove (List.remove_assoc) it, then merge x and y and prepend the merged value with the acc list, otherwise (if it is not in acc) just prepend (ky,y) to acc`. Note that this algorithm doesn't preserve order, so if it matters you need something more complex. Also, if your keys are sorted you can make it a little bit more efficient and easier to implement.
I guess you're doing this to practice with list.
What I would do is store the already found keys in an accumulator
let mergePairs yourList =
let rec aux accKeys = function
| [] -> []
| x :: xs -> let k,v = x in if (* k in accKeys *) then aux accKeys xs (*we suppress already
existing keys*)
else (k, v # (* get all the list of the other pairs with key = k in xs*))
:: aux (k::accKeys) xs
in aux [] yourList;;

Sort a list of tuples by their second element without higher order functions or recursion

I have a list of (String, Int) pairs and am struggling to figure out how to sort the list by the snd field (Int). I am not allowed to use higher order functions or recursion which makes it more difficult.
For example, I have
[("aaaaa", 5),("bghdfe", 6),("dddr",4)]
and would like to sort it into
[("dddr",4),("aaaaa", 5),("bghdfe", 6)].
Edit:
I understand that the sort may not be possible without higher order functions, what I really need is to find the element with the minimum length (the snd field), so is there a way to find the minimum number and then take the fst field of the list's element at that index? If that way works better I am unsure about how to find the index of that minimum number however.
The task seems to be impossible, since you can't write a sort without recursion in Haskell. This means, you must use sort, which is usually something like sortBy compare and thus you have it.
But if you are allowed to use sort you can do it by first reversing all tuples, sorting the resulting list and reversing the tuples in the result again. This should be possible to do in a few nested list comprehension, so technically no higher order functions are needed.
After you have given more details, I'd do
homework list = snd (minimum [ (s,f) | (f,s) <- list ])
Without higher order functions or recursion all you have left, technically, is list comprehensions. Thus we define
-- sortBy (comparing snd) >>> take 1 >>> listToMaybe >>> fmap fst
-- ~= minimumBy (comparing snd) >>> fst
foo :: Ord b => [(a,b)] -> Maybe a
foo xs = case [ a | (a,b) <- xs
, null [ () | (_c,d) <- xs, d < b]]
of (a:_) -> Just a
[] -> Nothing

How to select element from tuple by index in list?

I want to select elements from a list, [[1,2],[3,4],[5,6]] once the first, than the second, than again the first and so on.
I figured that i could use zip to add a counter in front of the pairs and use modulo to select the part, and now my list looks like this:
let a = [(0,[1,2]),(1,[3,4]),(2,[5,6]),(3,[7,8]),(4,[9,10])]
but how can I now select the elements?
the pseudocode would be
for each tuple in list:
first part of tuple is the selector, second part is the pair
if selector mod 2 : choose pair[0] else choose pair[1]
the output for the list a should be: 1,4,5,7,9
Perhaps:
> zipWith (!!) [[1,2],[3,4],[5,6],[7,8],[9,10]] (cycle [0,1])
[1,4,5,8,9]
If you know you're working with lists of length two inside, you should probably be using pairs instead.
> zipWith ($) (cycle [fst, snd]) [(1,2),(3,4),(5,6),(7,8),(9,10)]
[1,4,5,8,9]
I like #DanielWagner answer a lot. The first is so simple and effective. His second is a just a little harder to understand but simple, too. When theories are simple, it increases their veracity. Here is my sorry solution but it does use your structure. (Association lists are tuples. It was suggested you use tuples but for this, what you have and probably need is okay.)
a = [(0,[1,2]),(1,[3,4]),(2,[5,6]),(3,[7,8]),(4,[9,10])]
[if even i then x else y | (i,(x:y:z)) <- a]
[1,4,5,8,9]

List to List of List with all possible combination

First of all, I cannot remember the name of this repetition of list.
I have a list:
myList = [0, 1, 2]
I want to repeat list of list:
[[0,1,2],[1,2,0],...]
I know that I can do permutations myList
But it won't cover the repeated parts such as [[0,0,0],[1,1,1],[1,1,0],...]
So, my questions are what is the name given for such kind of list.
It is not permutations and it definitely is not combinations
In logic, we call it truth table, I believe.
And is there a builtin function for that in haskell?
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :m +Control.Monad
Prelude Control.Monad> replicateM 3 [0,1,2]
[[0,0,0],[0,0,1],[0,0,2],[0,1,0],[0,1,1],[0,1,2],[0,2,0],[0,2,1],[0,2,2],[1,0,0],[1,0,1],[1,0,2],[1,1,0],[1,1,1],[1,1,2],[1,2,0],[1,2,1],[1,2,2],[2,0,0],[2,0,1],[2,0,2],[2,1,0],[2,1,1],[2,1,2],[2,2,0],[2,2,1],[2,2,2]]
Note that basically, the length of the list of permitted values needs in no way be connected to the length of each list of choices.
with list comprehension
x = [0,1,2]
[[a,b,c] | a<-x, b<-x, c<-x]
[[0,0,0],[0,0,1],[0,0,2],[0,1,0],[0,1,1],[0,1,2],[0,2,0],[0,2,1],[0,2,2],
[1,0,0],[1,0,1],[1,0,2],[1,1,0],[1,1,1],[1,1,2],[1,2,0],[1,2,1],[1,2,2],
[2,0,0],[2,0,1],[2,0,2],[2,1,0],[2,1,1],[2,1,2],[2,2,0],[2,2,1],[2,2,2]]

Haskell - alternating elements from two lists

I'm trying to write a haskell function that takes in two lists of integers and generates a list with elements that have been taken alternatingly from the two lists.
I have the function:
blend xs ys
An example:
blend [1,2,3] [4,5,6]
should return
[1,4,2,5,3,6]
My logic is to zip the two lists together, generating the pairs of alternate elements, then somehow remove them from their tuples.
It's removing them from their tuples that I can't figure out how to implement.
How about exchanging the arguments during recursion-descend?
blend (x:xs) ys = x:(blend ys xs)
blend _ _ = []
You can even generalise this approach for any number of lists (I'll leave this to you) or take the remaining elements of a list if the other is empty:
blend _ ys = ys
If you want to zip, generate lists instead of tuples:
concat $ zipWith (\x y -> [x,y]) [1,2,3] [4,5,6]
Some pointless fun:
concat $ zipWith ((flip(:)).(:[])) [1,2,3] [4,5,6]
Probably the easiest way:
import Data.List
concat $ transpose [[1,2,3],[4,5,6]]
I will assume that this is homework. Provided that you can create the following list (as you said):
[(1,4),(2,5),(3,6)]
... you can solve it with 2 functions:
You need to convert a tuple (a, b) into a list [a, b]. Try using pattern matching! This function needs to be applied (aka. mapped) over all elements of the list you have.
You will have a list of lists, like [[1,4],[2,5],[3,6]], so you need a function for concatenating the sublists into one big list.
There are of course other, maybe superior, ways to solve this problem, but it might be a good idea to continue with your original approach.
A solution without using concat or explicit recursion:
blend l = foldr($)[] . zipWith(.) (map(:)l) . map(:)
We can make also make this point-free
blend' = (foldr($)[].) . (.map(:)) . zipWith(.) . map(:)
How it works: first decorate both lists with cons operators
\[1,2,3] [4,5,6] -> [1:, 2:, 3:] [4:, 5:, 6:]
then we zip this together with function composition
-> [(1:).(4:), (2:).(5:), (3:).(6:)]
and finally fold the application of all these compositions from the right to the empty list
-> (1:).(4:) $ (2:).(5:) $ (3:).(6:) $ [] = 1:4:2:5:3:6:[] = [1,4,2,5,3,6]
Your blend function seems to be a limited version of flatZip. The flatZip function is similar but works for any number of lists of varying lengths. Using flatZip to implement blend will cause blend to also support varying lengths by default. Therefore, using a flatZip based approach may not be the way to go in situations where trimming the input lists to equal length is part of the desired behaviour.
The name flatZip refers to "a zipish way of flattening". Note the -ish part though. We can implement the function by composing concat with transpose. We can add blend on top of flatZip as syntactic sugar to verify that our implementation matches the desired behaviour.
import Data.List
flatZip = concat . transpose
flatZip([[1,2],[3],[4,5,6]]) --[1,3,4,2,5,6]
blend xs ys = flatZip [xs, ys]
blend [1,2,3] [4,5,6] --[1,4,2,5,3,6]