Packages
otpbp
7.6.1
7.18.0
7.16.1
7.15.0
7.14.0
7.13.0
7.12.0
7.11.0
7.10.2
7.9.3
7.9.2
7.9.1
7.8.7
7.8.6
7.8.5
7.8.4
7.7.1
7.7.0
7.6.3
7.6.2
7.6.1
7.6.0
7.5.1
7.5.0
7.4.0
7.3.4
7.3.3
7.3.2
7.3.1
7.3.0
7.2.0
7.1.1
7.1.0
7.0.4
7.0.3
7.0.2
7.0.1
6.26.0
6.25.0
6.24.0
6.23.0
6.22.2
6.21.3
6.21.2
6.21.1
6.20.2
6.19.1
6.19.0
6.18.3
6.18.2
6.18.1
6.18.0
6.17.1
6.17.0
6.16.0
6.15.4
6.15.3
6.15.2
6.15.1
6.15.0
6.14.0
6.13.5
6.13.4
6.13.3
6.13.2
6.13.1
6.13.0
6.12.0
6.11.2
6.11.1
6.10.0
6.9.2
6.9.1
6.9.0
6.8.0
6.7.1
6.7.0
6.6.4
6.6.3
6.6.2
6.6.1
6.6.0
6.5.0
6.4.0
6.3.3
6.3.2
6.3.1
6.3.0
6.2.1
6.2.0
6.1.0
6.0.0
5.39.0
5.38.0
5.37.0
5.36.0
5.35.2
5.34.3
5.34.2
5.34.1
5.33.1
5.32.1
5.32.0
5.31.3
5.31.2
5.31.1
5.31.0
5.30.1
5.30.0
5.29.0
5.28.4
5.28.3
5.28.2
5.28.1
5.28.0
5.27.0
5.26.5
5.26.4
5.26.3
5.26.2
5.26.1
5.26.0
5.25.0
5.24.2
5.24.1
5.23.0
5.22.2
5.22.1
5.22.0
5.21.0
5.20.1
5.20.0
5.19.4
5.19.3
5.19.2
5.19.1
5.19.0
5.18.0
5.17.0
5.16.3
5.16.1
5.16.0
5.15.1
5.15.0
5.14.0
5.13.1
5.13.0
5.12.1
5.12.0
5.11.2
5.11.1
5.10.1
5.10.0
5.9.0
5.8.0
5.7.0
5.6.1
5.6.0
5.5.0
5.4.2
5.4.1
5.4.0
5.3.0
5.2.2
5.2.1
5.2.0
5.1.2
5.1.1
4.79.0
4.78.0
4.77.0
4.76.2
4.75.3
4.75.2
4.75.1
4.74.0
4.73.1
4.73.0
4.72.3
4.72.2
4.72.1
4.72.0
4.71.1
4.71.0
4.70.0
4.69.4
4.69.3
4.69.2
4.69.1
4.69.0
4.68.0
4.67.5
4.67.4
4.67.3
4.67.2
4.67.0
4.66.0
4.65.2
4.65.1
4.64.0
4.63.2
4.63.1
4.63.0
4.62.0
4.61.1
4.61.0
4.60.4
4.60.3
4.60.2
4.60.1
4.60.0
4.59.0
4.58.0
4.57.2
4.57.1
4.57.0
4.56.2
4.56.1
4.56.0
4.55.0
4.54.0
4.53.0
4.52.1
4.52.0
4.51.3
4.51.2
4.51.0
4.50.0
4.49.3
4.49.2
OTP backports
Current section
Files
Jump to
Current section
Files
src/otpbp_string.erl
-module(otpbp_string).
-ifndef(HAVE_string__jaro_similarity_2).
% OTP 27.0
-export([jaro_similarity/2]).
-endif.
-ifndef(HAVE_string__jaro_similarity_2).
jaro_similarity(A0, B0) ->
case {str_to_gcl_and_length(A0), str_to_indexmap(B0)} of
{{_, 0}, [_|0]} -> 1.0;
{{_, ALen}, [_|BLen]} when ALen =:= 0; BLen =:= 0 -> 0.0;
{{A, ALen}, [B|BLen]} ->
case jaro_match(A, B, max(ALen, BLen) div 2) of
{[], _} -> 0.0;
{AM, BM} ->
{M, T} = jaro_calc_mt(AM, BM, 0, 0),
(M / ALen + M / BLen + (M - T / 2) / M) / 3
end
end.
-compile({inline, jaro_match/3}).
jaro_match(A, B, Dist) -> jaro_match(A, B, -Dist, Dist, [], []).
jaro_match([A|As], B, Min, Max, AM, BM) ->
Min1 = Min + 1,
Max1 = Max + 1,
case jaro_detect(maps:get(A, B, []), Min, Max) of
false -> jaro_match(As, B, Min1, Max1, AM, BM);
{J, Remain} -> jaro_match(As, B#{A => Remain}, Min1, Max1, [A|AM], add_rsorted({J, A}, BM))
end;
jaro_match(_A, _B, _Min, _Max, AM, BM) -> {AM, BM}.
jaro_detect([Idx|Rest], Min, Max) when Idx < Max ->
if
Min < Idx -> {Idx, Rest};
true -> jaro_detect(Rest, Min, Max)
end;
jaro_detect(_, _, _) -> false.
jaro_calc_mt([Char|AM], [{_, Char}|BM], M, T) -> jaro_calc_mt(AM, BM, M + 1, T);
jaro_calc_mt([_|AM], [_|BM], M, T) -> jaro_calc_mt(AM, BM, M + 1, T + 1);
jaro_calc_mt([], [], M, T) -> {M, T}.
add_rsorted(A, [H|_] = BM) when A > H -> [A|BM];
add_rsorted(A, [H|BM]) -> [H|add_rsorted(A, BM)];
add_rsorted(A, []) -> [A].
-compile({inline, str_to_gcl_and_length/1}).
str_to_gcl_and_length(S0) -> gcl_and_length(unicode_util:gc(S0), [], 0).
gcl_and_length([C|Str], Acc, N) -> gcl_and_length(unicode_util:gc(Str), [C|Acc], N + 1);
gcl_and_length([], Acc, N) -> {lists:reverse(Acc), N};
gcl_and_length({error, Err}, _, _) -> error({badarg, Err}).
-compile({inline, str_to_indexmap/1}).
str_to_indexmap(S) -> str_to_map(unicode_util:gc(S), 0).
str_to_map([G|Gs], I) ->
[M|L] = str_to_map(unicode_util:gc(Gs), I + 1),
[M#{G => [I|maps:get(G, M, [])]}|L];
str_to_map([], L) -> [#{}|L];
str_to_map({error,Error}, _) -> error({badarg, Error}).
-endif.