Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get X first elements out of list

Tags:

haskell

Let’s consider 2 lists: ["a","b","c"] and ["a","b","c","d","e","f"]

I want to check if the first list is the beginning of the other list I thought I could use:

["a","b","c"] == head (splitAt (length ["a","b","c"]) ["a","b","c","d","e","f"])

Unfortunately this doesn't work. Is there another way to get the first the 3 first elements out of a list in a new list?

like image 980
Hans van der Laan Avatar asked Sep 24 '14 17:09

Hans van der Laan


People also ask

How do you extract the first element of a list in Python?

In Python lists are zero-indexed, so the first element is available at index 0 . Similarly, we can also use the slicing syntax [:1] to get the first element of a list in Python.

How do you print the first 5 elements of a list in Python?

To access the first n elements from a list, we can use the slicing syntax [ ] by passing a 0:n as an arguments to it . 0 is the start index (it is inculded). n is end index (it is excluded).

How do you get the first N elements of a list in Haskell?

There is a function in Haskell that takes first n elements of user-supplied list, named take . The syntax is: function-name arg1 arg2 . So, take takes first 1000 elements from an infinite list of numbers from 0 to infinity.


1 Answers

Rather than using take, you could use zipWith to avoid traversing the lists twice. When you call length, you first have to traverse the shorter list, then you take that many values from the longer list, then you traverse the lists, comparing element by element. What would make more sense is to traverse both lists as the same time, stopping your comparison when the shorter one is expired. zipWith provides exactly this functionality:

-- Definitions for `and` and `zipWith` in `Prelude`
--
-- and :: [Bool] -> Bool
-- and [] = True
-- and (x:xs) = x && and xs
--
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
-- zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
-- zipWith _ _      _      = []

sameStartingElements :: Eq a => [a] -> [a] -> Bool
sameStartingElements xs ys = and $ zipWith (==) xs ys

Thanks to laziness, this definition will only traverse both lists once, and it stops as soon as one of them runs out of elements. This will be somewhat more efficient, and it avoids having to know the length of either list.

like image 62
bheklilr Avatar answered Oct 13 '22 16:10

bheklilr