userver: userver/utils/distances.hpp Source File
Loading...
Searching...
No Matches
distances.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/distances.hpp
4/// @brief Distances between strings and nearest string suggestions
5
6#include <optional>
7#include <string>
8#include <string_view>
9#include <type_traits>
10
11USERVER_NAMESPACE_BEGIN
12
13namespace utils {
14
15namespace impl {
16
17std::string SuggestNameErrorMsg(std::optional<std::string_view> suggest_name);
18
19} // namespace impl
20
21/// Returns the Levenshtein distance between two strings.
22std::size_t GetLevenshteinDistance(std::string_view view1,
23 std::string_view view2);
24
25/// Returns the Damerau-Levenshtein distance between two strings.
26std::size_t GetDamerauLevenshteinDistance(std::string_view view1,
27 std::string_view view2);
28
29/// Returns a nearest string for a key from a bunch of strings.
30template <typename StringViews, typename DistanceFunc = std::size_t (*)(
31 std::string_view, std::string_view)>
35 static_assert(
36 std::is_convertible_v<decltype(*std::begin(strings)), std::string_view>,
37 "Parameter `strings` should be an iterable over strings.");
38
39 std::optional<std::string_view> nearest_str;
40 std::size_t min_distance = 0;
41 for (const auto& str : strings) {
42 std::string_view obj_view(str);
43 std::size_t cur_distance = distance_func(key, obj_view);
44 if (!nearest_str.has_value() || cur_distance < min_distance) {
45 nearest_str = obj_view;
46 min_distance = cur_distance;
47 }
48 }
49 if (nearest_str.has_value() && min_distance <= max_distance) {
50 return nearest_str;
51 }
52 return {};
53}
54
55/// Returns a suggestion for a key
56template <typename StringViews>
57std::string SuggestNearestName(const StringViews& strings,
58 std::string_view key) {
59 static_assert(
60 std::is_convertible_v<decltype(*std::begin(strings)), std::string_view>,
61 "Parameter `strings` should be an iterable over strings.");
62 constexpr std::size_t kMaxDistance = 3;
63 return impl::SuggestNameErrorMsg(
64 utils::GetNearestString(strings, key, kMaxDistance));
65}
66
67} // namespace utils
68
69USERVER_NAMESPACE_END