Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pairs of elements from list

I want to convert [1,2,3,4] to [[1 2] [2 3] [3 4]] or [(1 2) (2 3) (3 4)]. In clojure I have (partition 2 1 [1,2,3,4]). How can I do it in haskell? I suspect there is such function in standard api but I can't find it.

like image 883
piotrek Avatar asked May 26 '13 17:05

piotrek


People also ask

How do you pair elements in a list?

Pair iteration in a list using zip() + list slicing. The zip function can be used to extract pairs over the list slicing can be used to successively pair the current element with the next one for efficient pairing.

How do you get a pair of elements from a list in Python?

To join pairs of list elements in Python: Use the range() class with a step argument or 2. Use a list comprehension to iterate over the range of indexes. On each iteration, join the list item at the current index with the item at the next index.

What is a list of pairs?

A list is a combination of pairs that creates a linked list. More precisely, a list is either the empty list null, or it is a pair whose first element is a list element and whose second element is a list.

How do you make a pair in Python?

Practical Data Science using Python Follow the below steps to solve the problem. Initialize the lists with elements. Iterate over the lists and append the pair into a list if the corresponding elements from the lists are not same. Print the result.


1 Answers

The standard trick for this is to zip the list with it's own tail:

> let xs = [1,2,3,4] in zip xs (tail xs)
[(1,2),(2,3),(3,4)]

To see why this works, line up the list and its tail visually.

      xs = 1 : 2 : 3 : 4 : []
 tail xs = 2 : 3 : 4 : []

and note that zip is making a tuple out of each column.

There are two more subtle reasons why this always does the right thing:

  • zip stops when either list runs out of elements. That makes sense here since we can't have an "incomplete pair" at the end and it also ensures that we get no pairs from a single element list.
  • When xs is empty, one might expect tail xs to throw an exception. However, because zip checks its first argument first, when it sees that it's the empty list, the second argument is never evaluated.

Everything above also holds true for zipWith, so you can use the same method whenever you need to apply a function pairwise to adjacent elements.

For a generic solution like Clojure's partition, there is nothing in the standard libraries. However, you can try something like this:

partition' :: Int -> Int -> [a] -> [[a]]
partition' size offset
  | size <= 0   = error "partition': size must be positive"
  | offset <= 0 = error "partition': offset must be positive"
  | otherwise   = loop
  where
    loop :: [a] -> [[a]]
    loop xs = case splitAt size xs of
                -- If the second part is empty, we're at the end. But we might
                -- have gotten less than we asked for, hence the check.
                (ys, []) -> if length ys == size then [ys] else []
                (ys, _ ) -> ys : loop (drop offset xs)
like image 158
hammar Avatar answered Sep 23 '22 12:09

hammar