2017-04-10 8 views
0

パターンマッチする方法はありますか?ミドル| _last]エリクサーで?つまり、少なくとも3つのものがある(ただしそれ以上の場合が多い)が、頭と最後の要素以外はすべて一致するリストに一致させたい。パターンマッチエリクシルのリストの真ん中

例:あなたのケースは非常に特異的であるため

def match_middle([_head | middle | _last]) do 
     IO.inspect middle 
    end 

    match_middle [1, 2, 3, 4, 5] 
    >>> [2, 3, 4] 
+0

おそらくありません – JustMichael

+0

最初と最後の要素を除いたリストを抽出するだけではなく、パターンマッチしてもよろしいですか? – GavinBrelstaff

+0

@GavinBrelstaff私はパターンマッチングについて特に疑問を抱いていましたが、あなたがそれを行う簡潔な方法を持っているなら、私はそれを見たいと思います。私は現在、心に来た最初のものを使用しています。コメントの書式を設定する方法はありません....ここでは、セミコロンを使用して方法をガイドしています。 [_ |残り] =アイテム; [_last | rest_backwards] = Enum.reverse残り; middle = Enum.reverse(rest_backwards) – MaxStrange

答えて

1

List.pop_at/3は再帰、:lists.reverse、と頭のアクセスを使用して自分自身を実現しています。つまり、リストの最後の要素に直接アクセスする方法はありません。

リストでNの要素、たとえば、より多くのあり得ないことを懸念、ある一方、直接パターンマッチがまだ達成可能である:

defmodule MatchInTheMiddle do 
    @n 10 
    Enum.each([email protected], fn i -> 
    @match_clause Enum.map(0..i, fn j -> {:"p#{j}", [], Elixir} end) 
    def match_middle(unquote(
     [{:_head, [], Elixir}] ++ @match_clause ++ [{:_last, [], Elixir}]) 
    ), do: IO.inspect unquote(@match_clause) 
    end) 
end 

そして、はい、短いと長いリストのための優雅なフォールバック:

def match_middle([]), do: [] 
def match_middle([_]), do: [] 
def match_middle([_head | tail]) do 
    with [_tail | middle] <- :lists.reverse(tail), do: middle 
end 

MatchInTheMiddle.match_middle([1,2,3,4]) 
#⇒ [2,3] 

これは、おそらくそれがあることが予想ほどエレガントではありませんが、これらの句は上のパターンマッチとにをコンパイルしているので、いくつかのケースでは、それは、役に立つかもしれません胡データの量がこれよりも効率的です。Enum操作。

+0

ガードやパターンマッチで使用できる表現に最も近いです。確かに、スーパーエレガントではない。 – MaxStrange

2

Propably私は、パターンマッチングなしていることを解決するだろう - あなたはmiddleは、最初と最後の要素以外のすべてですが、スプリットオペレータは異なる方法で動作することを前提と - それを最初の要素とそれ以外の要素のリストをtailとして分割します。あなたのケースでは

私は真ん中を一致させるためのプライベート関数を作成します。

defp get_middle_from_list(list) do 
    list 
    |> Stream.drop(1) 
    |> Stream.drop(-1) 
    |> Enum.to_list() 
end 

を、リストには少ないし、3つの要素が含まれている場合、それは[]を返します。それにもちろん

get_middle_from_list [1, 2, 3, 4, 5] 
> [2, 3, 4] 

を使用しています。

3

エリクシールリストは、実際にはLispの初期の段階に戻るコンスリストです。

iex(1)> foo = [1 ,2 , 3] 
[1, 2, 3] 
iex(2)> [ head | [ middle | tail ]] = foo 
[1, 2, 3] 
iex(3)> middle 
2 

我々は[1,2,3]としてそれを書きながら、だから、それは本当にあなたが求めているものをカバーしていないこと、しかし本当に[1, [2,[3,[]]]]

です。あなたが見るかもしれませんが、このような何かは多分

def match_middle([_head | [ second | tail]]) when tail != [] do 
    flip_tail = Enum.reverse(tail) 
    [end | rest] = flip_tail 
    [second | Enum.reverse(rest) ] 
end 
+0

正直なところ、これは "_pattern match_ something like' [_head |ミドル| _last] '、" e。 g。ガードには使用できません。 – mudasobwa

関連する問題