我在Elixir中构建了一个二分查找,但最终使用了3个if语句:
if actual == guessed_number, do:
if actual > guessed_number do:
if actual < guessed_number do:
完全不使用条件语句是可能的吗?也许可以使用模式匹配?
我在Elixir中构建了一个二分查找,但最终使用了3个if语句:
if actual == guessed_number, do:
if actual > guessed_number do:
if actual < guessed_number do:
免责声明:本文不适用于生产环境,因为链表不支持常数时间内的随机访问,因此比简单的线性搜索要慢。本文只是关于模式匹配方面的内容。
理论上你可以使用守卫条款,但如果过度使用会使情况变得更糟。假设你从像这样的实现开始:
defmodule MyEnum do
def binsearch(collection, key) do
binsearch(collection, key, 1, length(collection))
end
defp binsearch(collection, key, lo, hi) do
if hi < lo do
-1
else
mid = div(lo + hi, 2)
item = Enum.at(collection, mid)
cond do
key < item -> binsearch(collection, key, lo, mid-1)
key > item -> binsearch(collection, key, mid+1, hi)
true -> mid
end
end
end
end
if
提取为一个守卫条款:defmodule MyEnum do
def binsearch(collection, key) do
binsearch(collection, key, 1, length(collection))
end
defp binsearch(_collection, _key, lo, hi) when hi < lo do
-1
end
defp binsearch(collection, key, lo, hi) do
mid = div(lo + hi, 2)
item = Enum.at(collection, mid)
cond do
key < item -> binsearch(collection, key, lo, mid-1)
key > item -> binsearch(collection, key, mid+1, hi)
true -> mid
end
end
end
cond
移到守卫子句中,但这并不是真正的改进:defmodule MyEnum do
def binsearch(collection, key) do
binsearch(collection, key, 1, length(collection))
end
defp binsearch(_collection, _key, low, hi) when hi < low do
-1
end
defp binsearch(collection, key, low, hi) do
mid = div(low + hi, 2)
item = Enum.at(collection, mid)
binsearch(collection, key, item, low, mid, hi)
end
defp binsearch(collection, key, item, low, mid, _hi) when key < item do
binsearch(collection, key, low, mid-1)
end
defp binsearch(collection, key, item, _low, mid, hi) when key > item do
binsearch(collection, key, mid+1, hi)
end
defp binsearch(_collection, _key, _item, _low, mid, _hi) do
mid
end
end
使用模式匹配无法完成这个任务。但是,你可以使用类似于 Erlang 的 if
的 cond
:
cond do
actual == guessed_number ->
...
actual > guessed_number ->
...
actual < guessed_number ->
...
end
Enum.at
的运行时间为线性的,因此这种二分搜索比简单的线性搜索要慢。 - John La RooyO(log(n)
二分查找。 - Vitalii Elenhaupt