【发布时间】:2017-06-12 10:29:46
【问题描述】:
我有一个文件名列表,每个文件名代表一个时间点。该列表通常包含数千个元素。给定一个时间点,我想把这些文件名转换成时间对象(我用的是boost::ptime),然后找到这个时间点的std::lower_bound相对于文件名的值。
例子:
文件名(日期+时间,分钟递增,每个文件一分钟):
station01_20170612_030405.hdf5
station01_20170612_030505.hdf5
station01_20170612_030605.hdf5
station01_20170612_030705.hdf5
station01_20170612_030805.hdf5
station01_20170612_030905.hdf5
如果我有一个时间点2017-06-12 03:06:00,那么它适合这里:
station01_20170612_030405.hdf5
station01_20170612_030505.hdf5
<--- The lower bound I am looking for is here
station01_20170612_030605.hdf5
station01_20170612_030705.hdf5
station01_20170612_030805.hdf5
station01_20170612_030905.hdf5
到目前为止,一切都很简单。现在的问题是文件列表中可能掺杂了一些无效的文件名,这会导致到时间点的转换失败。
目前,我正在以简单/低效的方式执行此操作,并且我想对其进行优化,因为该程序将在服务器上运行,并且操作成本很重要。所以,愚蠢的做法是:创建一个带有时间点的新列表,并且只推送有效的时间点:
vector<ptime> filesListTimePoints;
filesListTimePoints.reserve(filesList.size());
ptime time;
for(long i = 0; i < filesList.size(); i++) {
ErrorCode error = ConvertToTime(filesList[i], time);
if(error.errorCode() == SUCCESS)
filesListTimePoints.push_back(time);
}
//now use std::lower_bound() on filesListTimePoints
你看,问题是我使用了一个线性解决方案,这个问题可以用O(log(N)) 复杂度来解决。我不需要转换所有文件,甚至不需要查看所有文件!
我的问题:如何将其嵌入到 std::lower_bound 中,以使其保持最佳复杂度?
我对可能解决方案的想法:
在cppreference 上,有一个std::lower_bound 的基本实现。我正在考虑修改它以获得一个可行的解决方案。但是我不确定当转换失败时该怎么办,因为该算法高度依赖于单调行为。这个问题有解决方案吗,甚至在数学上?
这是我最初考虑的版本:
template<class ForwardIt, class T>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value)
{
ForwardIt it;
typename std::iterator_traits<ForwardIt>::difference_type count, step;
count = std::distance(first, last);
while (count > 0) {
it = first;
step = count / 2;
std::advance(it, step);
ErrorCode error = ConvertToTime(*it, time);
if(error.errorCode() == SUCCESS)
{
if (*it < value) {
first = ++it;
count -= step + 1;
}
else
count = step;
}
else {
// skip/ignore this point?
}
}
return first;
}
我的最终解决方案(这可能听起来很愚蠢)是让这个方法成为列表的突变体,并删除无效的元素。有更清洁的解决方案吗?
【问题讨论】:
-
你能实现你自己的
Compare并传递它吗? -
@Incomputable 由于搜索方法的单调性,这是一个不切实际的解决方案。比较器将返回真/假。当文件名无效时,此比较器返回的答案是什么?
-
所以无效的没有任何订购信息?
-
@Incomputable 不!想想看……我提供的列表示例中抛出的随机文件。它怎么可能与任何时间点相关联?它实际上是一个无效文件,应该完全忽略。
标签: c++ algorithm performance boost time-complexity