mackeyja92

mackeyja92

`Enum.map_every/3` but with start offset

There is sometimes cases where you want to map every nth item starting on the nth item. Eg map every 2nd item starting on the 2nd one. Currently the map_every/3 always gives back the first item in the enumerable and then every nth item. I propose to add an optional parameter to the function for the offset for the first item. Another option would be to add a parameter to start on the nth item instead but that’s probably less flexible than the offset. What’s your thoughts? Is there another way to do this with the existing APIs?

Most Liked

tomekowal

tomekowal

I believe that is a perfectly fine solution. If you need to perform different operations on even and odd elements you could also try chunking the list.

E.g.

[1,2,3,4,5,6]
|> Enum.chunk_every(2)
# [[1,2], [3,4], [5,6]]
|> Enum.map(fn [first, second] -> [first*2, second*3] end)
|> List.flatten
# [2, 6, 6, 12, 10, 18]

That doubles every odd element and triples every even one.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

@mackeyja92 I’d probably use Enum.drop.
eg: “Map every 4th thing starting on the 2nd thing”

list |> Enum.drop(2) |> Enum.map_every(4, fun)
mackeyja92

mackeyja92

The problem with drop is it removes the items from the list. If you only need to do a certain operation on nth items but need to do another operation on the whole list after you’re stuck with removing items and storing in a temporary list and then pushing them back on the front after the map_every.

A real world example is the Luhn checksum.

# Reverse them first                                                                                                                                                                                                                                                                        
numbers = Enum.reverse(numbers)                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                            
# Pop the first one off because elixir always does the first one when using map_every                                                                                                                                                                                                       
{first, numbers} = List.pop_at(numbers, 0)                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                            
numbers                                                                                                                                                                                                                                                                                     
|> Enum.map_every(2, fn num ->                                                                                                                                                                                                                                                              
  num = num * 2                                                                                                                                                                                                                                                                             
  # If the number after doubling is greater than 9 then subtract 9                                                                                                                                                                                                                          
  if num > 9 do                                                                                                                                                                                                                                                                             
    num - 9                                                                                                                                                                                                                                                                                 
  else                                                                                                                                                                                                                                                                                      
    num                                                                                                                                                                                                                                                                                     
  end                                                                                                                                                                                                                                                                                       
end)                                                                                                                                                                                                                                                                                        
# Put the first one back                                                                                                                                                                                                                                                                    
|> List.insert_at(0, first)                                                                                                                                                                                                                                                                 
# Sum them all                                                                                                                                                                                                                                                                              
|> Enum.sum()                                                                                                                                                                                                                                                                               
# If the modulo of 10 is 0 then it is a valid checksum                                                                                                                                                                                                                                      
|> Kernel.rem(10)                                                                                                                                                                                                                                                                           
|> Kernel.==(0)   

Last Post!

shjeon0730

shjeon0730

found a simple solution:
basic concept is, adding a dummy value at the beginning, and choose tail later.

list=[1,2,3,4,5]
Enum.map_every(list, 2, & &1+10)
[11, 2, 13, 4, 15]
[99 | list] |> Enum.map_every(2, & &1+10) |> tl
[1, 12, 3, 14, 5]

for more offset, comprehension would work.

for i <- 1..5 do i end ++ list |> Enum.map_every(7, & &1+10) |> Enum.drop(5)
[1, 2, 13, 4, 5]

if it is just alternate pattern and need to choose offset 0 or 1, it might be useful

Where Next?

Popular in Discussions Top

PragTob
Hey everyone, this has been on my mind for some time and I’d love your input on it! TLDR: I feel like maps are superioer for storing and...
New
chuck
Let me start by stating an assumption: Phoenix is a great approach to building REST APIs. There are many reasons for this, but I will ass...
New
thojanssens1
It would be nice to be able to define a redirect from one route to another from the router.ex file. E.g.: redirect "/", UserController, ...
New
mikl
I wanted to capitalize a string, and tried using String.capitalize(). That generally works well, until you try to capitalize a word like...
New
opsb
We’re considering our architecture from a viewpoint of scaling our traffic heavily over the next 6 months. Our current deployment is runn...
New
RudManusachi
What configs will make sense to put to runtime.exs? – A bit of how I configure apps: I have generic configs in config/config.exs, dev...
New
nunobernardes99
Hi there Elixir friends :vulcan_salute: In a recent task I was on, I needed to check in two dates which of them is the maximum and which...
New

Other popular topics Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54996 245
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40082 209
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42576 114
New

We're in Beta

About us Mission Statement