2016-12-02 29 views
1

這可能是一個微不足道的問題,但我無法繞開它。如何在Elixir中獲得一個範圍的尾巴

我只是想模式匹配的範圍,獲得頭部和尾部。

這裏是我的嘗試:

iex(1)> [h|t] = [1..3] 
[1..3] 
iex(2)> h 
1..3 
iex(3)> t 
[] 

正如你所看到的,它不會做什麼我的預期。我的期望是h = 1t = [2,3]

我該如何獲得一個範圍內的頭部和尾部?這甚至可能嗎?

回答

4

首先,[1..3]是一個包含1範圍,而不是範圍的列表。其次,範圍本身不是一個列表,它只是一個包含2個值的結構:第一個和最後一個值(Map.from_struct(1..10) #=> %{first: 1, last: 10})。如果你想有一個範圍內列表的頭部和尾部,你需要的範圍內轉換到一個列表第一:

iex(1)> range = 1..3 
1..3 
iex(2)> list = Enum.to_list(range) 
[1, 2, 3] 
iex(3)> [h | t] = list 
[1, 2, 3] 
iex(4)> h 
1 
iex(5)> t 
[2, 3] 

注意,這是非常低效的取決於你在做什麼。一個範圍佔用很少的內存(一個Struct + 2個整數鍵)。列表將佔據與列表中項目數量成比例的空間。取決於你在做什麼,可能比將範圍轉換爲列表更好。

0

最有效的方法可能是隻是抓住它從底層AST:

iex(6)> Macro.escape(1..10) 
{:%{}, [], [__struct__: Range, first: 1, last: 10]} 

因此...

{:%{}, [], [__struct__: Range, first: head, last: tail]} = Macro.escape(range) 

iex(10)> head 
1 
iex(11)> tail 
10 

編輯:使用quoteMacro.escape似乎是這裏更強大

0

你可以通過它的inde X

iex(1)> range = 1..3      
1..3 
iex(2)> last_index = Enum.count(range) - 1 
2 
iex(3)> Enum.at(range, last_index)   
3 
1

這應該更好地工作

iex(42)> range = 1..100  
1..100 
iex(43)> _..last = range  
1..100 
iex(44)> last 
100 
+0

很不錯的!我不知道你可以這樣做。 +1 – Simone