2016-07-31 39 views
0

是否有可能将范围传给Elixir的Enum.filter。对于例如如何在Elixir中将范围传递给Enum.filter?

这工作

[1,2,3,4,5] |> Enum.filter(&rem(&1,2)==0) #=> [2,4] 

但这并不

[1..10] |> Enum.filter(&rem(&1,2)==0) #=> bad argument in arithmetic... 

我有一个包含我想传递给筛选范围的列表。例如。

[1..10, 2, 3] 

回答

3

你不需要把它包装在[]

iex(1)> 1..10 |> Enum.filter(&rem(&1,2)==0) 
[2, 4, 6, 8, 10] 

[1..10]是长度为1以等于范围1..10第一元件的列表。如果你想创建可读性范围时使用括号,只需使用()

iex(2)> [1..10, 2, 3] |> Enum.flat_map(fn 
...(2)> n when is_number(n) -> if rem(n, 2) == 0, do: [n], else: [] 
...(2)> enum -> Enum.filter(enum, &rem(&1, 2) == 0) 
...(2)> end) 
[2, 4, 6, 8, 10, 2] 
+0

啊,这是有道理的。但是,我如何通过一个列表来过滤具有范围元素的列表?例如这里是我想要按照上面过滤的列表'list = [1..10,2,3]'。 – Bala

+0

您可以使用'Enum.to_list(1..10)++ [2,3]'将其转换为平面列表,并将其传递给'Enum.flat_map',并在那里运行'Enum.filter'如果该项目是一个范围,否则返回'[]'或'[x]'如果该项目是一个数字。 – Dogbert

+0

我已经添加了第二种方法的实现。 – Dogbert

2


要过滤包含数字和范围的清单,我会用Enum.flat_map这样。

(1..10) |> Enum.filter(&rem(&1,2)==0) 

在你的榜样最可读的解决办法是:

# declare anonymous function for checking is number even 
is_even = &rem(&1,2) == 0 
(1..10) |> Enum.filter(&is_even.(&1)) 
+2

在第二个中,您可以执行'|> Enum.filter(is_even)''。 :) – Dogbert

+0

@Dogbert:如果你可以在没有第二个'&,&1'的情况下抛出指针,我将不胜感激。我的意思是什么时候我需要'&',而当我不需要时? – Bala

+1

@Bala'Enum.filter'需要匿名函数,即'fn ... end'。 '&'语法用于将模块的函数转换为匿名函数。在这种情况下'is_even'已经是一个匿名函数。 '&is_even。(&1)'是多余的,相当于只是'is_even'。 – Dogbert