我正在尝试将price
字段(它是一个字符串(例如"2.22"
或""
)转换为float或nil,然后将其添加到数据库中。
def insert_product_shop(conn, product_id, shop_id, price) do
priceFloat = nil
if price not in [""] do
price = elem(Float.parse(price), 0)
priceFloat = price / 1
IO.inspect(priceFloat)
else
priceFloat = nil
end
IO.inspect(priceFloat)
changeset = Api.ProductShop.changeset(%Api.ProductShop{
p_id: product_id,
s_id: shop_id,
price: priceFloat,
not_in_shop_count: 0,
is_in_shop_count: 0
})
errors = changeset.errors
valid = changeset.valid?
IO.inspect(changeset)
case insert(changeset) do
{:ok, product_shop} ->
{:ok, product_shop}
{:error, changeset} ->
{:error, :failure}
end
end
输出为:
2.22
nil
#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #Api.ProductShop<>,
valid?: true>
13:25:41.745 [debug] QUERY OK db=2.0ms
INSERT INTO "product_shops" ("is_in_shop_count","not_in_shop_count","p_id","s_id") VALUES ($1,$2,$3,$4) RETURNING "id" [0, 0, 40, 1]
如输出所示,priceFloat
变为零,我认为是因为当我将其设置为2.22时,它不在范围内。也许我的代码太必要了。如何重写此代码以将“ 2.22”转换为2.22,而不使其变为nil,并允许将“”转换为nil?
您可以使用case
来评估Float.parse
的返回值,并在返回nil
时分配:error
,前提是if
的目的是避免解析错误
def insert_product_shop(conn, product_id, shop_id, price) do
priceFloat = case Float.parse(price) do
{value, _remainder} -> value
:error -> nil
end
...
end
如输出所示,priceFloat变为nil,因为我将其设置为2.22时超出了范围。
几乎正确。问题在于,您要设置的变量不在范围内,而是问题是您分配给inside if语句的变量在范围[
price = "2.22"
priceFloat =
if price not in [""] do
elem(Float.parse(price), 0)
else
nil
end
IO.inspect(priceFloat)
但是,它仍然不是很惯用。您可以利用以下事实:当输入为空字符串时,Float.parse/1
返回:error
可以像使用case
表达式那样将其写入:
priceFloat = case Float.parse(price) do {float, ""} -> float :error -> nil end
defmodule Example do
def parsePrice(""), do: nil
def parsePrice(price) when is_float(price), do: price
def parsePrice(price) when is_binary(price) do
{float, _} = Float.parse(price)
float
end
end
Example.parsePrice(2.22) |> IO.inspect
Example.parsePrice("2.22") |> IO.inspect
((使用case
语句可以实现等效项)如果将非二进制(字符串)或浮点数的任何内容传递给此函数,将导致模式不匹配的错误。如果您有一些错误报告,这可能会很好,这样您就可以检测到代码的意外使用。
为了获得更好的调试体验,建议您通过
IEx.pry/0
使用内置调试器。
IEx.pry/0
特殊形式的方法。with/1
这里我们仅明确匹配浮点数。任何尾随的垃圾将被丢弃。如果匹配成功,则返回浮点数,否则,返回with {f, ""} <- Float.parse("3.14"), do: f, else: (_ -> nil)
。
[小心nil
可能被看起来像科学记数法的垃圾所混淆。
Float.parse/1