キーワードリスト、何だったかというあたりからのリハビリになるのか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
別件あるんで今日はここでエントリ投入します。どうしたものか。