sagnik2911
Finding maximum match (contiguously from begining) string from a list of strings for a string
I am facing a problem in iterating over a list of string and finding the one matches the most with the input string. As I see, any assignment to any variable inside the Enum.each does not stay once we are out of Enum.each.
Suppose I have a string, name = “A123”.
List of String for searching the closest, list = [“AAAA”,“A129”,“A451”,“A134”,“B321”,“A522”]
For our string “A123”, this should return me “A129” (Matches 3 characters from beginning)
If we have a string, name = “A732”, we should get the string “AAAA” (Matches 1 characters from beginning).
For a string, name = “A472”, we should get the string “A451” (Matches maximum 2 characters from beginning).
How can I implement this in Elixir?
Marked As Solved
kip
This might give you some ideas:
defmodule Match do
@list ["AAAA","A129","A451","A134","B321","A522"]
def nearest(key, list \\ @list) do
Enum.reduce list, {"", 0}, fn item, {nearest, distance} ->
if (maybe_nearer = String.jaro_distance(key, item)) > distance do
{item, maybe_nearer}
else
{nearest, distance}
end
end
end
def longest(key, list \\ @list) do
Enum.reduce list, {"", 0}, fn item, {nearest, length} ->
match =
key
|> String.myers_difference(item)
|> Keyword.get(:eq)
if (len = String.length(match || "")) > length do
{item, len}
else
{nearest, length}
end
end
end
def leading(key, list \\ @list) do
Enum.reduce list, {"", 0}, fn item, {nearest, distance} ->
match_length = String.length(item) - String.length(String.trim_leading(item, key))
if match_length > distance do
{item, match_length}
else
{nearest, distance}
end
end
end
end
I’m using String.jaro_distance/2 here to define “nearest” and String.myers_difference/2 to define “longest” but of course you can substitute whatever “nearest” or “longest” means to you. [Update] I added Match.leading/2 to match the longest leading prefix but its not at all efficient.
Examples
iex> Match.longest "A1"
{"A129", 2}
iex> Match.nearest "A1"
{"A129", 0.8333333333333334}
iex> Match.leading "A1"
{"A129", 2}
iex> Match.leading "Z"
{"", 0}
Also Liked
kip
And your question is?
kip
Thanks, thats much more helpful. This is a really good community, but just posting exceptions isn’t likely to encourage much engagement or support.
The exception is raised because when there is no substring matching match will be nil. I have updated the code above to handle this outcome.
Its great to ask more questions, but please let us know what you’ve tried as well.
kip
Also I doubt String.myers_difference/2 will match the max leading substring either. I think thats something you’ll have to implement. I’m just trying to give you some approaches to take using the standard library.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









