【问题标题】:Idiomatic C++ for finding a range of equal length strings, given a vector of strings (ordered by length)给定字符串向量(按长度排序),用于查找一系列等长字符串的惯用 C++
【发布时间】:2011-05-29 11:56:19
【问题描述】:

给定一个std::vector< std::string >,向量是按字符串长度排序的,我怎样才能找到一个长度相等的范围?

我期待 C++ 中的惯用解决方案。

我找到了这个解决方案:

// any idea for a better name? (English is not my mother tongue)
bool less_length( const std::string& lhs, const std::string& rhs )
{
    return lhs.length() < rhs.length();
}

std::vector< std::string > words;
words.push_back("ape");
words.push_back("cat");
words.push_back("dog");
words.push_back("camel");
size_t length = 3;
// this will give a range from "ape" to "dog" (included):
std::equal_range( words.begin(), words.end(), std::string( length, 'a' ), less_length );

有没有标准的方法(漂亮地)?

【问题讨论】:

    标签: c++ string stl


    【解决方案1】:

    我希望您可以编写如下比较器:

    struct LengthComparator {
        bool operator()(const std::string &lhs, std::string::size_type rhs) {
            return lhs.size() < rhs;
        }
        bool operator()(std::string::size_type lhs, const std::string &rhs) {
            return lhs < rhs.size();
        }
        bool operator()(const std::string &lhs, const std::string &rhs) {
            return lhs.size() < rhs.size();
        }
    };
    

    然后使用它:

    std::equal_range(words.begin(), words.end(), length, LengthComparator());
    

    我希望operator() 的第三个重载永远不会使用,因为它提供的信息是多余的。范围必须预先排序,因此算法比较范围中的两个项目没有意义,它应该将范围中的项目与您提供的目标进行比较。但标准并不能保证这一点。 [编辑:定义所有三个意味着您可以使用相同的比较器类首先将向量按顺序排列,这可能很方便]。

    这对我有用(gcc 4.3.4),虽然我认为这也适用于您的实现,但我不太确定它是否真的有效。它实现了equal_range 的描述所说的结果为真的比较,并且25.3.3/1 不要求模板参数T 必须与迭代器引用的对象的类型完全相同。但是我可能遗漏了一些增加了更多限制的文本,所以在将它用于任何重要的事情之前,我会做更多的标准拖网。

    【讨论】:

    • 谢谢,“有效”是否意味着“符合 C++ 标准”?
    • 是的,我使用它很松散,但“有效”实际上是指“按照标准保证做你想做的事”。严格来说,它的意思是“由标准保证具有定义的行为”,并且没有执行您想要的操作的代码仍然是“有效的”,但在这种情况下,我看不出有什么不同 - 这是您获得的唯一方法错误的答案是,如果某些技术性意味着我编写的代码以某种方式违反了equal_range 的先决条件。
    • 它适用于 Microsoft Visual Studio 2008 (15.00.30729.01)。我做了一个非常有限的测试。
    • @uvts_cvs:是的,对于equal_range 的任何给定实现,您可能只需检查lower_boundupper_bound 的实现,看看它是否会起作用。我只是担心在某处有一些关于整个算法的通用文本说“比较器必须执行 X、Y 和 Z”,即使大多数实现根本不依赖 Z。​​
    【解决方案2】:

    你的方式绝对不是单一的,但是必须构造一个具有目标长度的虚拟字符串看起来不是很优雅,也不是很可读。

    我可能会编写自己的辅助函数(即string_length_range),在字符串列表中封装一个简单的循环。一切都不需要使用std:: 工具。

    【讨论】:

    • 谢谢。你说得对,我不太喜欢虚拟字符串:-|
    • 根据数据的大小和所需的性能,使用二分搜索可能很有用(因为字符串是按长度排序的)。
    • 我同意,二分搜索会有好处。
    【解决方案3】:

    std::equal_range 进行二分搜索。这意味着必须对 words 向量进行排序,在这种情况下,这意味着它的长度必须不递减。

    我认为您的解决方案是一个很好的解决方案,绝对比编写自己的二进制搜索实现更好,因为它容易出错且难以证明是正确的。

    如果进行二分搜索不是您的本意,那么我同意 Alexander 的观点。只需一个简单的 for 循环遍历单词是最干净的。

    【讨论】:

    • 是的,我需要二进制搜索,并且向量按字符串长度排序(如问题标题所述)。
    猜你喜欢
    • 2015-06-29
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    相关资源
    最近更新 更多