我将一些元组存储在Elixir :ets表中,格式如下:
{id, "first_name", "last_name"}我希望在ETS表中搜索名字和姓氏,给出一个搜索词。例如,如果某人的名字是Alice,搜索将返回"Al“、"Ali”、"Alic“等的元组。
到目前为止,我已经尝试过:
:ets.match_object(table_name, {:_, :_, "last_name"})当它与"last_name“完全匹配,但如果我在搜索字符串中有"last”或一些较短的排列,它就不会返回结果。
我还研究了搜索向量、ets.match、ets.lookup和其他一些执行搜索的方法。有没有内置的或者其他灵巧的方法来进行这种类型的字符串搜索?
发布于 2021-11-09 12:03:29
记住,您在Erlang中有通用的比较规则,这意味着您可以比较字符串"Alice"和"Al",因为它们只是列表。
现在到了有趣的部分:
table = :ets.new(:table, [:protected, :set])
:ets.insert(table, {1, "Alice", "Dannings"})
:ets.insert(table, {2, "Ali", "Aaqib"})
:ets.insert(table, {3, "Bob", "Dannings"})
:ets.insert(table, {4, "Amanda", "Clarke"})
:ets.insert(table, {5, "Al", "Clarke"})
# now let's explore elixir comparison rules
"Alice" >= "Al"
"Alice" < "Am"
# based on rules above we can make a selector which will be equivalent to starts_with?
selector = :ets.fun2ms(
fn({_, x, _} = y) # match all three element tuples
when # where
x >= "Al" and x < "Am" # second element is greater or equal to "Al" and less than "Am" ("m" is the next letter in the alphabet)
-> y end)
:ets.select(table, selector)
#[{1, "Alice", "Dannings"}, {2, "Ali", "Aaqib"}, {5, "Al", "Clarke"}]虽然您可以通过字符串的开头“搜索”,但这很麻烦。
如果你想在运行时使用它,你必须在模块的开头设置@compile {:parse_transform, :ms_transform},或者使用像https://github.com/ericmj/ex2ms这样的库,以确保正确地生成匹配规范(选择器)。
发布于 2021-11-17 05:46:00
可以使用:ets.foldl/3这把ets查找的瑞士刀。
:ets.foldl(fn
{_, "Al" <> _, _} = y, acc -> [y | acc] # firstname
{_, _, "Al" <> _} = y, acc -> [y | acc] # lastname
_, acc -> acc # no match
end, [], table)请注意,与@MikhailAksenov提出的解决方案相比,这种方法的效率较低,因为搜索是在调用过程中完成的,因此所有数据都必须传输到那里,而不是在ets中进行过滤。
https://stackoverflow.com/questions/69889517
复制相似问题