C++ 使用std::equal_range查找字符串向量中出现的前缀范围
我试图找到一个lambda,它允许C++ 使用std::equal_range查找字符串向量中出现的前缀范围,c++,string,search,range,C++,String,Search,Range,我试图找到一个lambda,它允许std::equal_range返回一个范围,其中搜索的字符串作为前缀存在。由于措辞可能不正确,举个例子: 给定字符串向量: C:\users\andy\documents\screenshot.jpg C:\users\bob\desktop\file.txt C:\users\bob\desktop\picture.png C:\users\bob\desktop\video.mp4 C:\users\john\desktop\note.txt 我希望返
std::equal_range
返回一个范围,其中搜索的字符串作为前缀存在。由于措辞可能不正确,举个例子:
给定字符串向量:
- C:\users\andy\documents\screenshot.jpg
- C:\users\bob\desktop\file.txt
- C:\users\bob\desktop\picture.png
- C:\users\bob\desktop\video.mp4
- C:\users\john\desktop\note.txt
- C:\users\bob\desktop\file.txt和
- C:\users\bob\desktop\video.mp4
我该如何为
std::equal_range
编写一个比较lambda来实现这一点,或者std::equal_range
不是适合此工作的工具?我认为您只需要让比较器将前缀的长度与如下元素进行比较:
std::vector<std::string> v
{
"C:/users/andy/documents/screenshot.jpg",
"C:/users/bob/desktop/file.txt",
"C:/users/bob/desktop/picture.png",
"C:/users/bob/desktop/video.mp4",
"C:/users/john/desktop/note.txt",
};
std::sort(std::begin(v), std::end(v));
std::string const prefix = "C:/users/bob/desktop/";
auto lb = std::lower_bound(std::begin(v), std::end(v), prefix);
// For the upper bound we want to view the vector's data as if
// every element was truncated to the size of the prefix.
// Then perform a normal match.
auto ub = std::upper_bound(lb, std::end(v), prefix,
[&](std::string const& s1, std::string const& s2)
{
// compare UP TO the length of the prefix and no farther
if(auto cmp = std::strncmp(s1.data(), s2.data(), prefix.size()))
return cmp < 0;
// The strings are equal to the length of the prefix so
// behave as if they are equal. That means s1 < s2 == false
return false;
});
// make the answer look like we used std::equal_range
// (if that's what's needed)
auto range = std::make_pair(lb, ub);
for(auto itr = range.first; itr != range.second; ++itr)
std::cout << *itr << '\n';
为了解释为什么这样做,想象一下获取向量并对其进行排序。然后想象访问每个元素并将它们截断为前缀的长度。您将得到一个排序后的向量,其元素长度不超过前缀。在这一点上,一个简单的
std::equal_range
将满足您的要求。因此,我们需要做的就是构造一个比较器,它的行为就像容器元素被截断到前缀的长度一样,并在我们的std::equal_range
搜索(或twinstd::lower_bound/upper_bound
搜索)中使用该比较器.std::equal_range的四个参数重载以及comparison callable对象似乎足以完成任务。只需编写一个实现与前缀匹配的比较的比较对象。为了返回正确的比较结果,您必须小心地使用对比较对象进行编码。这似乎可行,但我不确定它是否完全正确:您可能可以使用std::string来避免substr
。compare
,但这对我来说更清楚。shrugI将采取比退休忍者更复杂的方法。我会将前缀字符串强制转换为一个不同的助手类型,该类型不是std::string
。然后我可以区分这两种类型的比较函数,并在自定义比较器类中实现两个操作符()
s,比较前缀和字符串,和字符串的前缀。那么C:\users\bob\desktop\picture.png
为什么不应该返回它呢?使用=
打破了严格的弱排序要求进行比较。这个答案比我能解释得更好。:)根据我对Sam Varshavchik上述评论的理解,您必须同时使用comp(元素,值)和comp(值,元素)进行比较,对吗?另外,在这里使用string::compare会更快吗?@AndrewLeFevre是的,你是对的。这比我想象的要复杂。我会再考虑一下的。@AndrewLeFevre我相信这个问题已经解决了。
C:/users/bob/desktop/file.txt
C:/users/bob/desktop/picture.png
C:/users/bob/desktop/video.mp4