In Elm, how would you get every even index in a list and return as another list?
So you want to return only even-indexed items from a list, right?
Here's how you could do that writing your own function. We'll write a helper function, everySecond_
, that looks like this.
everySecond_ : List a -> Int -> List a
everySecond_ list index =
case list of
[] ->
[]
hd :: tl ->
if index % 2 == 0 then
hd :: (everySecond_ tl (index + 1))
else
everySecond_ tl (index + 1)
This function takes a list, and a number representing what index the current head of that list has. We need to pass that as an argument to the function.
Then we pattern-match on the list. If it's empty, we return an empty list; this signals the end of recursion. The last element in a list is always an empty list. If it's not an empty list, we take the head (the first element) and the tail (a list representing everything onward).
If our index
argument was even (% 2 == 0
means "when divided by two, leaves no remainders"), we want to keep this element, so we append it to the front of the list we're building up, and continue to build by calling everySecond_
again with the tail of our current list and an incremented index number.
If it's not even, we don't want to keep this element, so we just return everySecond_ tl (index + 1)
, the next stage of the list, and the process repeats.
That's the logic of it. But that means we'd need to call everySecond_ [foo, bar, baz] 1
to use our function, always passing in 1 as a default argument. That's not intuitive. And that's why we called it everySecond_
with an underscore -- this isn't what we're going to have people call, this is a helper function that'll exist behind the scenes. We can hide this behind
everySecond : List a -> List a
everySecond list =
everySecond_ list 1
Now you call everySecond [foo, bar, baz]
and it works fine, basically defaulting the starting index to 1.
An even simpler way of doing this would be to not keep track of the index at all, but to use a boolean (True/False) value. You start with a False, and instead of testing for divisibility by 2, you just check the boolean. If it's True, you keep the element, and call the function again with False; if it's False, you ignore the element and call the function again with True.