2017-01-15 3 views
1

文字列中の単語の出現回数を数えたいと思います。実装は疑問ですが、私の問題を示すためにそれを使用することができます:エリクシルでパイプされた値を参照する

def count(sentence) do 
    words = String.split(sentence) 
    occurrences = Enum.map(words, fn w -> {w, Enum.count(words, &(&1 == w))} end) 
    Map.new(occurrences) 
    end 

私は、上記と同じ結果を達成するために好きですが、代わりに中間結果変数のパイプを使用します:

def count(sentence) do 
    sentence 
    |> String.split 
    |> Enum.map(fn w -> {w, Enum.count(???)} end) 
    |> Map.new 
    end 

がそれですEnum.count関数でパイプされた値を参照することは可能ですか?または中間変数を使用する必要がありますか?

答えて

6

あなたはパイプラインで匿名関数を置くことができます。

def count(sentence) do 
    sentence 
    |> String.split 
    |> (fn words -> Enum.map(words, fn w -> {w, Enum.count(words, &(&1 == w))} end) end).() 
    |> Map.new 
end 
@ Dogbertの答えは完全に正しいですが
iex(1)> count("foo bar baz foo") 
%{"bar" => 1, "baz" => 1, "foo" => 2} 
4

が、私は追記を追加します。あなたが必要とするや否やようですパイプアウト値が2回あると、間違っている可能性があります。上記の例は、のように書き換えることがあります(および、したがって、全体機能のビッグO

def count(sentence) do 
    sentence 
    |> String.split 
    |> Enum.reduce(%{}, fn e, acc -> 
    Map.put(acc, e, (Map.get(acc, e) || 0) + 1) 
    end) 
end 

又は関与するループの量を減少させる多くの他の方法で

+1

でこれを使用して見たOPはすでに、ちょうどそのコードを使用していたことを知っていたようにそれが見えたとして(私は私の答えで、より良いアルゴリズムを提案していませんでした"実装は疑わしいですが、私の問題を実証するために使用することができます。"ということを例として挙げています)。 – Dogbert

+0

私のポイントは決して:パイプのvarを2回使用することは避けられない場合があります。 – mudasobwa

+0

私の最終的な解決策は、それだけでなく、私が興味を持ったのは、ドッグベルトが悩んでいたものです。それは、私は匿名関数のアプローチは混乱していると思うし、間違いなくあなたのソリューションのようなものに置き換えてください。 –

0

地図.updateはかなりエレガントな方法でこれを実現します。私はホセValim自身がラムダ日2017年

def count_words(words) do 
    words 
    |> String.split() 
    |> Enum.reduce(%{}, &count/2) 
    end 

def count(word, map) do 
    Map.update(map, word, 1, & &1 + 1) 
end 

iex(1)> Word.count_words("I know we can yes we can can") 
%{"I" => 1, "can" => 3, "know" => 1, "we" => 2, "yes" => 1} 
関連する問題