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, std::string_view view2);
23
24/// Returns the Damerau-Levenshtein distance between two strings.
25std::size_t GetDamerauLevenshteinDistance(std::string_view view1, std::string_view view2);
26
27/// Returns a nearest string for a key from a bunch of strings.
28template <typename StringViews, typename DistanceFunc = std::size_t (*)(std::string_view, std::string_view)>
30 const StringViews& strings,
34) {
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
40 std::optional<std::string_view> nearest_str;
41 std::size_t min_distance = 0;
42 for (const auto& str : strings) {
43 std::string_view obj_view(str);
44 std::size_t cur_distance = distance_func(key, obj_view);
45 if (!nearest_str.has_value() || cur_distance < min_distance) {
46 nearest_str = obj_view;
47 min_distance = cur_distance;
48 }
49 }
50 if (nearest_str.has_value() && min_distance <= max_distance) {
51 return nearest_str;
52 }
53 return {};
54}
55
56/// Returns a suggestion for a key
57template <typename StringViews>
58std::string SuggestNearestName(const StringViews& strings, 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 );
63 constexpr std::size_t kMaxDistance = 3;
64 return impl::SuggestNameErrorMsg(utils::GetNearestString(strings, key, kMaxDistance));
65}
66
67} // namespace utils
68
69USERVER_NAMESPACE_END