如何改进我的矢量搜索功能?

Posted

技术标签:

【中文标题】如何改进我的矢量搜索功能?【英文标题】:How do I improve my vector search function? 【发布时间】:2019-03-23 16:18:35 【问题描述】:

所以我在 C++ 中实现了一个 TCP 服务器,并将所有用户存储在一个向量中。现在我需要一个更通用的函数来搜索多个不同的属性,我该如何改进这段代码?

struct client 
    std::string ip_address = "";
    int socket_id = 0;
    bool blocking = false;
;

enum client_codes 
    ip_address,
    socket_id,
    blocking,
;

template<typename T>
std::vector<client>::iterator search_vector(std::vector<client> &list, int type, T query) 

    std::vector<std::function<bool(client)>> comparators;

    comparators.push_back([&](client ob) return ob.ip_address == std::to_string(query); );
    comparators.push_back([&](client ob) return ob.socket_id == query; );
    comparators.push_back([&](client ob) return ob.blocking == query; );

    return std::find_if(std::begin(list), std::end(list), [&](client obj) return comparators[type](obj); );



// Implementation
std::vector<client> client_list;
auto search1(search_vector(client_list, socket_id, 321));
auto search2(search_vector(client_list, blocking, true));
auto search3(search_vector(client_list, ip_address, "192.168.0.85"));

【问题讨论】:

要询问已经工作的代码的改进,您最好在SE Code Review 询问。 “搜索多个不同的属性”到底是什么意思?能举个例子吗? 保持简单。没有理由填充向量然后将索引传递到向量中直接传递适当的谓词。或者有简单的(可能是内联的)函数,比如FindBySocketId。这样,您遵循 DRY 原则,并本地化了解数据保存方式的内部细节的代码,如果在某些时候需要改进代码,这有助于维护。 【参考方案1】:

由于您正在搜索相同类型的不同属性,我想说这是pointers to members 的一个罕见用例。下面的代码应该有助于清理它:

struct client 
    std::string ip_address = "";
    int socket_id = 0;
    bool blocking = false;
;

// search_vector accepts a pointer to member of type T, and a value of type T
template<typename T>
std::vector<client>::iterator search_vector(std::vector<client>& list, T client::*member, T value)
    return std::find_if(list.begin(), list.end(), [value, member](const client& c) return c.*member == value; );

这就是您现在使用它的方式,无需任何额外的enums 或特殊逻辑。

auto it1 = search_vector(client_list, &client::socket_id, 321);
auto it2 = search_vector(client_list, &client::blocking, true);
auto it3 = search_vector(client_list, &client::ip_address, "192.168.0.85");

这个精确的search_vector 函数当然仅限于成员变量和精确的相等测试。但是使用指向成员函数的指针来扩展它是相当简单的,比如get_ip_address()

为了更笼统,当您不希望完全相等时,使用类似 std::function&lt;bool(T)&gt; condition 而不是 T value 的重载也可以帮助您进行更具体的搜索。

【讨论】:

【参考方案2】:

以下是一些建议:

    假设您多次搜索客户端向量 - 而不是使用 std::find_if,对向量进行排序并执行二分搜索(例如,使用 std::equal_range)。如果您经常添加新客户端,请考虑使用最近添加的客户端的附加、小型、未排序缓冲区,并偶尔将两者集成到一个排序向量中。 不要将检查搜索类型的代码放在谓词中 - 这样它会一次又一次地运行;而且您还需要基于堆的比较器向量 - 啊! ...而不是在搜索类型上模板您的搜索功能,并让它使用单个比较器。使用选择适当搜索函数的包装函数。

【讨论】:

以上是关于如何改进我的矢量搜索功能?的主要内容,如果未能解决你的问题,请参考以下文章

如何转换自定义矢量化器以预测分类?

ECS控制台实例搜索的优化与改进

如何改进大数据的矢量化滑动窗口?

第07章 改善用户搜索体验

改进 sql 中的文本搜索

Windows 10 20H1 2004新功能