/var/log/messages

Jan 22, 2019 - 3 minute read - Comments - programming

プログラミング Elixir (10)

キーワードリスト、何だったかというあたりからのリハビリになるのかorz

とりあえず

確認を。

iex(26)> tax_rates = [ NC: 0.075, TX: 0.08]
[NC: 0.075, TX: 0.08]

参照が以下。

iex(30)> tax_rates[:NC]
0.075
iex(31)> tax_rates[:TX]
0.08

注文リストが以下か。

iex(32)> orders = [
...(32)> [ id: 123, ship_to: :NC, net_amount: 100.00],
...(32)> [ id: 124, ship_to: :OK, net_amount: 35.50],
...(32)> [ id: 125, ship_to: :TX, net_amount: 24.00],
...(32)> [ id: 126, ship_to: :TX, net_amount: 44.80],
...(32)> [ id: 127, ship_to: :NC, net_amount: 25.00],
...(32)> [ id: 128, ship_to: :MA, net_amount: 10.00],
...(32)> [ id: 129, ship_to: :CA, net_amount: 102.00],
...(32)> [ id: 130, ship_to: :NC, net_amount: 50.00] ]
[
  [id: 123, ship_to: :NC, net_amount: 100.0],
  [id: 124, ship_to: :OK, net_amount: 35.5],
  [id: 125, ship_to: :TX, net_amount: 24.0],
  [id: 126, ship_to: :TX, net_amount: 44.8],
  [id: 127, ship_to: :NC, net_amount: 25.0],
  [id: 128, ship_to: :MA, net_amount: 10.0],
  [id: 129, ship_to: :CA, net_amount: 102.0],
  [id: 130, ship_to: :NC, net_amount: 50.0]
]

要素の追加は Keyword.put、あるいは探索は Keyword.fetch で良いらしい。だとすると

  • 注文のリストを先頭から順に手繰りつつ
  • Keyword.keys で tax_rates の key を順に取り出して先頭の :ship_to に存在するか確認
  • 存在したら net_amount とかけざんして total_amount に put してリストにして戻す
  • 存在しなければ net_amount wol total_amount に put してリストにして戻す

なんだろう、横着になってて無理矢理リストにして戻して ++ で、って癖が付いてます。

ListsAndRecursion - 8

ええと、Keyword.fetch って、キー指定らしい。

iex(45)> test_kl                                        
[id: 123, ship_to: :NC, net_amount: 100.0]
iex(46)> Keyword.fetch(test_kl, :ship_to)
{:ok, :NC}

ちなみに put の例が以下。

iex(47)> Keyword.put(test_kl, :total_amout, 100.10)
[total_amout: 100.1, id: 123, ship_to: :NC, net_amount: 100.0]

なんとなくアイデアを書いてみる。というか色々面倒だな。もっかい整理。

  • copyorder は注文のリスト [head | tail] と tax_rates を引数に取る
  • (できれば) [_calc_total(head, tax_rates) | _calc_total(tail, tax_rates)] を戻す
  • _calc_total([head | []], tax_rates) は head なリストの total_amount の計算?
  • _calc_total([head | tail], tax_rates) は [_calc_total(head, tax_rates) | _calc_total(tail, tax_rates)] を戻す?

とするとどうなるのか。head について tax_rates を使って計算する手続きがあれば良いのか。

ええと

Keyword.keys(tax_rates)[:NC, :TX] を戻すんですがこれって内包表記で書けるのかな。む、これでええのか。

iex(52)> for x <- Keyword.values(test_kl), y <- Keyword.keys(tax_rates), x == y, do: x
[:NC]

や、これって無かったら駄目ですね。紆余曲折の末に以下を発見。

iex(57)> for x <- Keyword.values(test_kl), y <- Keyword.keys(tax_rates), x == y, do: Keyword.get(tax_rates, y)
[0.075]
iex(58)> for x <- Keyword.values(test2_kl), y <- Keyword.keys(tax_rates), x == y, do: Keyword.get(tax_rates, y)
[]

空リストなら 1 を掛けるか。ちょっと関数型でない感がアレですが別途見直します。アイデアを元にすると下書きてきには以下なカンジなのかどうか。

defmodule MyEnum do
  def copyorder([head | tail], tax_rates) do
    [_calc_total(head, tax_ratex) | _calc_total(tail, tax_rates)]
  end
  defp _calc_total(item, tax_tates) do
    rates = for x <- Keyword.values(item), y <- Keyword.keys(tax_rates), x == y, do: Keyword.get(tax_rates, y)
    if rates == [] do
      rates = 1
    else
      rates = List.first(rates)
    end
    Keyword.put(item, :total_amount, Keyword.get(item, :net_amount) * rates)
    item
  end
  defp _calc_total([head | []], tax_rates) do
    _calc_total(head, tax_rates)
  end
  defp _calc_total([head | tail], tax_rates) do
    [_calc_total(head, tax_rates) | _calc_total(tail, tax_rates)]
  end
end

ハマッています

現状、以下な実装なんですが

  def copyorder([head | tail], tax_rates) do
    [_calc_total(head, tax_rates) | _calc_total(tail, tax_rates)]
  end
  defp _calc_total([head | []], tax_rates) do
    [_calc_total(head, tax_rates)]
  end
  defp _calc_total([head | tail], tax_rates) do
    [_calc_total(head, tax_rates) | _calc_total(tail, tax_rates)]
  end
  defp _calc_total(item, tax_rates) do
    rates = for x <- Keyword.values(item), y <- Keyword.keys(tax_rates), x == y, do: Keyword.get(tax_rates, y)
    if rates == [] do
      rates = 1
    else
      rates = List.first(rates)
    end
    Keyword.put(item, :total_amount, Keyword.get(item, :net_amount) * List.first(rates))
    item
  end

一番下の _calc_total な item に {id: 123} という情報が渡されて Keyword じゃないよね、って叱られています。

どうもこれ

head の head を取得しているらしい。あ、リストじゃんかorz

別件あるんで今日はここでエントリ投入します。どうしたものか。

プログラミング Elixir (9) プログラミング Elixir (11)

comments powered by Disqus