【问题标题】:How to get the tail of a range in Elixir如何在 Elixir 中获得范围的尾部
【发布时间】:2017-04-17 12:49:17
【问题描述】:

这可能是一个微不足道的问题,但我无法理解。

我只想在一个范围内进行模式匹配,获取头部和尾部。

这是我尝试过的:

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

如您所见,它没有达到我的预期。我的期望是h = 1t = [2,3]

如何让头部和尾部超出范围?这可能吗?

【问题讨论】:

    标签: pattern-matching elixir


    【解决方案1】:

    借用 edwinallenz 的回答(优雅但只返回最后一个元素),以下返回头部和尾部,同时也接近 OP 的想法:

    iex(1)> first..last = 1..5
    1..5
    iex(2)> [h | t] = [first | first+1..last]
    [1 | 2..5]
    

    Dogbert 的回答解释了 Elixir 范围的语法糖:脱掉妆容,在 1..5 下方,您会找到结构 %Range{first: first, last: last}。 因此,上面直接使用底层结构将是这个笨拙的事情:

    iex(1)> r = %Range{first: 1, last: 5}     
    1..5
    iex(2)> [h | t] = [r.first | %Range{first: r.first+1, last: r.last}]
    [1 | 2..5]
    

    【讨论】:

      【解决方案2】:

      这应该会更好

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

      【讨论】:

      • 非常好!我不知道你能做到这一点。 +1
      【解决方案3】:

      您可以通过索引获取范围的最后一项

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

      【讨论】:

        【解决方案4】:

        最有效的方法可能是从底层 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 似乎在这里更强大

        【讨论】:

          【解决方案5】:

          首先,[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]
          

          请注意,这取决于您正在做什么,效率非常低。一个范围占用很少的内存(一个结构 + 2 个整数键)。列表将占用与列表中项目数成比例的空间。根据您的操作,可能有比将范围转换为列表更好的方法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-09-28
            • 2019-01-23
            • 2020-10-20
            • 2019-05-02
            • 2011-11-06
            • 2022-08-18
            • 1970-01-01
            • 2010-09-07
            相关资源
            最近更新 更多