Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the most efficient way to take up to the last n elements of a list

Tags:

haskell

To clarify : I want all the elements but the last n

Reading some answers on stackoverflow I get the impression that using length on lists is inadvisable. So is there better way to do this than take (length xs - n) xs?

like image 592
squirrels Avatar asked Oct 16 '20 13:10

squirrels


People also ask

How do you find the last N elements of a list?

Use the slicing syntax list[-n:] to get a list containing the last n elements of list .

What is the best way to find the number of elements in a list?

The most straightforward way to get the number of elements in a list is to use the Python built-in function len() . As the name function suggests, len() returns the length of the list, regardless of the types of elements in it.

How do I get the last 5 elements of a list in Python?

To get the last element of the list in Python, use the list[-1] syntax. The list[-n] syntax gets the nth-to-last element. So list[-1] gets the last element, and list[-2] gets the second to last. The list[-1] is the most preferable, shortest, and Pythonic way to get the last element.

How do you find the last N elements of a list in Haskell?

To obtain the last n elements of a list xs , I can use reverse (take n (reverse xs)) , but that is not very good code (it keeps the complete list in memory before returning anything, and the result is not shared with the original list).

How to get the last element of a list using list reversed?

reversed () coupled with next () can easily be used to get the last element, as like one of the naive method, reversed method returns the reversed ordering of list as an iterator, and next () method prints the next element, in this case last element. test_list = [1, 4, 5, 6, 3, 5]

What is the difference between list[len-1] and List [-1]?

list [ len - 1 ] : Points to last element by definition. list [-1] : In python, negative indexing starts from end. The list.pop () method is used to access the last element of the list.

What is the most effective way to take notes?

Studies have found note taking is most effective when notes are organised and transformed in some way or when a teacher gives examples of good notes. An effective note-taking strategy requires effort.

How to remove the last element from a list in Java?

The pop () method is used to access the last element of the list and returns the removed item. The pop () method accepts an integer as the argument, which is basically the index of the item which needs to be removed from the list. Example – list.pop (0) will remove and return the first element in the list.


1 Answers

Yes. You first drop n elements from the list, then walk over the two lists concurrently and when the you hit the end of the list with the dropped version of the list, then you return the list of the "iterator" over the entire list:

takeLast :: Int -> [a] -> [a]
takeLast n ls = go (drop n ls) ls
    where go [] ls = ls
          go (_:xs) ~(_:ys) = go xs ys

This thus works because the first "iterator" is n steps ahead. So if it hits the end of the list, the second iterator is n steps behind the end of the list.

For example:

Prelude> takeLast 2 [1,4,2,5,1,3,0,2]
[0,2]
Prelude> takeLast 3 [1,4,2,5,1,3,0,2]
[3,0,2]
Prelude> takeLast 4 [1,4,2,5,1,3,0,2]
[1,3,0,2]
Prelude> takeLast 5 [1,4,2,5,1,3,0,2]
[5,1,3,0,2]

We can also drop the last n elements in a similar way:

dropLast :: Int -> [a] -> [a]
dropLast n ls = go (drop n ls) ls
    where go [] _ = []
          go (_:xs) ~(y:ys) = y : go xs ys

For example:

Prelude> dropLast 2 [1,4,2,5,1,3,0,2]
[1,4,2,5,1,3]
Prelude> dropLast 3 [1,4,2,5,1,3,0,2]
[1,4,2,5,1]
Prelude> dropLast 4 [1,4,2,5,1,3,0,2]
[1,4,2,5]
Prelude> dropLast 5 [1,4,2,5,1,3,0,2]
[1,4,2]

If we operate on an infinite list, then dropLast will still yield elements, whereas if we would use take (length ls - n) ls, it would get stuck in an infinite loop.

We can, as @DanielWagner says use zipWith for this:

dropLast :: Int -> [a] -> [a]
dropLast n xs = zipWith const xs (drop n xs)

Here we let zipWith iterate over both lists, and we use const to each time return the element of the first list.

like image 174
Willem Van Onsem Avatar answered Oct 17 '22 19:10

Willem Van Onsem