Elixir 列表模式匹配 ~ 在使用列表模式匹配常量后得到 x

Posted

技术标签:

【中文标题】Elixir 列表模式匹配 ~ 在使用列表模式匹配常量后得到 x【英文标题】:Elixir list pattern matching ~ get x after constant with list pattern matching 【发布时间】:2017-06-11 18:23:01 【问题描述】:

Elixir 是否以任何方式处理与常量相关的匹配值? 这方面的一个例子是 ::

所有的例子都是这个想法的伪语法

(之后的值)3 = x iex> [ _ | [ 3 | [ x | _ ] ] ] = [1,2,3,4,5,6,7] // x = 4 (6之前的值)=x iex> [ _ | [ x | [ 6 | _ ] ] ] = [1,2,3,4,5,6,7] // x = 5 (3 到 6 之间的值的子列表)= x iex> [ _ | [ 3 | [ x | [ 6 | _ ] ] ] ] = [1,2,3,4,5,6,7] // x = [4,5] (4后3个值的子列表)= [a,b,c] iex> [ _ | [ 3 | [ [a,b,c] | _ ] ] = [1,2,3,4,5,6,7] // x = [5,6,7]

不幸的是,大多数书籍和在线文档仅涵盖从第一个索引开始的绝对定位,例如通过 [ head | tail ] 从头部开始的 N 个元素,但随着目标值离第一个元素越来越远,使用 [ _ | [ _ | [ _ | [ x | _ ] ] ] ] 之类的语法变得有点愚蠢获取列表中的第 4 个元素。

是否有任何语法可以匹配列表的相对索引?一个不正确但在概念上合理的语法示例是通过 [ _ | [ x | [] ] ] 获取列表中的最后一个索引或通过 [ _ | [ 3 | [ x | _ ] ] ] 获取索引 3 之后的值

【问题讨论】:

请提供示例输入和预期输出,真的很难理解您要实现的目标。 预期输出是否更清楚?我完全知道这段代码无效,但应该证明目标。 【参考方案1】:

Elixir/Erlang 不支持模式匹配列表中未知位置的项目,因此您提到的 4 种情况都不能通过模式匹配完成。

唯一可以简化的是您想要列表的第 4 个元素。而不是:

[_ | [_ | [_ | [x | _]]]]

您可以使用该模式:

[_, _, _, x | _]
iex(1)> [_, _, _, x | _] = [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
iex(2)> x
4

【讨论】:

【参考方案2】:

您正在滥用 Elixir 中已知的模式匹配。当您有兴趣在列表中查找值时,没有模式

——(后面的值)3 = x

iex> [_, x | _] = Enum.drop_while([1,2,3,4,5,6,7], fn e -> e != 3 end)
#⇒ x = 4

——(6之前的值)=x

iex> [x | _] = [1,2,3,4,5,6,7]
...> |> Enum.take_while(fn e -> e != 6 end)
...> |> Enum.reverse
#⇒ x = 5

—(3 到 6 之间值的子列表)= x

iex> [_ | x] = [1,2,3,4,5,6,7]
...> |> Enum.drop_while(fn e -> e != 3 end)
...> |> Enum.take_while(fn e -> e != 6 end)
#⇒ x = [4, 5]

—(4后3个值的子列表)= [a,b,c]

iex> [1,2,3,4,5,6,7] 
...> Enum.drop_while(fn e -> e != 4 end)
...> Enum.slice(1..3)
#⇒ [5,6,7]

Enum.

【讨论】:

我不会称之为滥用模式匹配本身。模式匹配的思想并不局限于固定位置模式。

以上是关于Elixir 列表模式匹配 ~ 在使用列表模式匹配常量后得到 x的主要内容,如果未能解决你的问题,请参考以下文章

Elixir模式匹配协议实现者

使用模式匹配交换列表中的元素对

如何使用模式匹配在scala中获取一个nonEmpty列表?

如何在模式匹配中拆分列表?

在erlang中列出尾部模式匹配

列表推导加模式匹配