2016-05-05 7 views
0

匿名関数への外部値を修正、私はまだルビーから来エリクサーを学んでいるように私はこれについて間違った道を進んだことを絶対的に確信しています...エリクシール - まず

私はのリストを取得YouTubeからの検索結果を表示し、最も多く閲覧した動画を抽出しようとしています。

# html is the contents of the search results page 
metas = html |> Floki.find(".yt-lockup-meta-info > li") 

counter = -1 
index = -1 
high_views = 0 

Enum.each(metas, fn(li) -> 
    counter = counter + 1 
    text = Floki.text(li) 
    case String.split(text, " ") do 
    [count, "views"] -> 
     views = String.to_integer(String.replace(count, ",", "")) 
     IO.puts(">>> #{counter} - #{to_string(views)} views") 
     if views > high_views do 
     high_views = views 
     index = counter 
     end 
    [age, time_measurement, "ago"] -> 
     nil 
    end 
end) 

metasこのようなliタプルのリストです:

[{"li", [], ["2 years ago"]}, {"li", [], ["5,669,783 views"]}, 
{"li", [], ["9 years ago"]}, {"li", [], ["17,136,804 views"]}, 
... 
{"li", [], ["1 year ago"]}, {"li", [], ["15,217 views"]}, 
{"li", [], ["8 years ago"]}, {"li", [], ["909,053 views"]}] 

Enum.eachに渡された匿名関数は、独自のスコープを持ち、indexの値を設定していないので、これは動作しませんおよびhigh_views

外部スコープの値を匿名関数に渡す方法はありますか?それとももっと良い質問ですが、これをやってどうすればいいですか?

私はそれを動作させ、その後コードをリファクタリングすることを意図しましたが、私は立ち往生しています。助けてくれてありがとう。

答えて

0

私が推測したように、私は本当にそれについてすべて間違っていました。ここで私は、この作品を作ってしまった方法は次のとおりです。

だから、
defp extract_song_url_from_youtube_response(html = _) do 
    sorted = html 
    |> Floki.find(".yt-lockup-content") 
    |> Enum.sort(fn(item1, item2) -> view_count(item1) > view_count(item2) end) 

    [_, id] = Enum.at(sorted, 0) 
    |> Floki.find("h3 > a") 
    |> Floki.attribute("href") 
    |> Enum.find(fn(x) -> x =~ "/watch" end) 
    |> String.split("=") 
    "https://www.youtube.com/embed/" <> id 
end 

defp view_count(item) do 
    meta = item |> Floki.find(".yt-lockup-meta-info > li") 
    views = case Enum.at(meta, 1) do 
    {"li", _, viewlist} -> 
     parts = String.split(Enum.at(viewlist, 0), " ") 
     String.to_integer(String.replace(Enum.at(parts, 0), ",", "")) 
    nil -> 
     # most likely a playlist 
     0 
    end 
end 

、代わりに無名関数のスコープ外から変数を変更しようとしているのは、私はHTMLの階層にまで後ずさりし、並べ替え、各<div>結果に基づいて動画が受信した視聴回数。

エリクサーはただ驚くばかりです。一度私の頭を包み込んで、ルビーのようなものを強制しようとするのを止めることができます。

+0

'Enum.sort_by(items、&view_count/1)'へのソートを単純化する 'Enum.sort_by'があります。 –

6

エリクシールは不変です。関数はクロージャであるため、外部変数はそこに表示されますが、それらを変更することはできません。それらは再バインドのみできますが、その再バインドは内部の無名関数スコープにとどまります。

しかし、あなたがしようとしているツールはすべてEnumモジュールにあります。

あなたは本質的に、最大のビューを持つインデックスを探しています。 Enum functionsを見てみましょう。 Enum.max_by/2は有望です。それは、私たちが最大にしたい値を返す列挙型と関数を取ります。 Enum.with_index/1とそれをペアにしてリストを取り、タプルの各要素をその要素のインデックスでラップします。

インプリメンテーションとの主な違いは、内部関数が外部状態を変更しようとするのではなく、引数に基づいて値を返すことです。

私は単純なcatch-all _に「何もしない」ケースを崩壊させ、youtubeビデオに負のビュー数がないという前提で-1を返します。あなたの例を直線的に翻訳すると、ここでゼロ(あなたのhigh_viewsの初期値)が返されます。それはおそらく安全でしょう。

+0

Thanks @ martin-svalin。私はこれも私にそこに入るだろうと確信しています。私はエリクサーとのより多くの問題を解決する必要があると思う。 – Midwire

+0

もちろん、インデックスではなく要素のみが必要な場合は、 'with_index'関数を削除し、無名関数の引数のパターンを変更し、' IOを削除することができます。puts'デバッグ –

関連する問題