2

您好,我有一个std::vector<std::string>包含日期时间的内容,例如2011-03-23T12:23:32.123我想生成 2 个int 20110323和的向量122332123

我正在使用一个C++名为 Rcpp 的库(我认为这不是真正的问题,但你永远不知道,所以我放了Rcpp标签)

我做了这个可以完成这项工作,但速度很慢,我怎样才能加快速度?

Rcpp::List datetimeToInt(vector<string> datetimes){

    const int N=datetimes.size();
    Rcpp::IntegerVector date(N);  //please consider those as std::vector<int>
    Rcpp::IntegerVector time(N);

    //this is what I want to speed up
    for(int i=0; i<N; ++i){
        datetimes[i].erase(std::remove_if(datetimes[i].begin(), datetimes[i].end(), not1(ptr_fun(::isdigit))), datetimes[i].end());
        date[i] = atoi(datetimes[i].substr(0,8).c_str());
        time[i] = atoi(datetimes[i].substr(8,12).c_str());
    }

    return Rcpp::List::create(_["date"]=date, _["time"]=time); 
}
4

3 回答 3

1

您的代码非常优化,您可以做的唯一更改是替换这部分

    datetimes[i].erase(std::remove_if(datetimes[i].begin(), datetimes[i].end(), not1(ptr_fun(::isdigit))), datetimes[i].end());
    date[i] = atoi(datetimes[i].substr(0,8).c_str());
    time[i] = atoi(datetimes[i].substr(8,12).c_str());

使用更复杂和优化的东西,例如像这样的 smt (但我没有测试它):

int dateId = 0;
int timeId = 0;
char time_c[9];
char date_c[8];

for (int strId = 0; i < str.length(); ++strId) {
    if (isdigit(datetimes[i][strId]) {
        if (dateId >= 8) {
            time_c[timeId] = datetimes[i][strId];
            ++timeId;
        } else {
            date_c[dateId] = datetimes[i][strId];
            ++dateId;
        }
    } 
}

date[i] = atoi(date_c);
time[i] = atoi(time_c);

它仅在一次传递中将您的字符串分成两部分

于 2013-06-19T09:53:08.010 回答
1

使用 a std::vector<std::string>,我们必须制作字符串的副本。这是浪费时间。当您直接使用数据时,您应该使用CharacterVector不需要制作副本的 a。

// [[Rcpp::export]]
List datetimeToInt2(CharacterVector datetimes){

    const int N=datetimes.size();
    IntegerVector date(N); 
    IntegerVector time(N);
    std::string current ; 

    //this is what I want to speed up
    for(int i=0; i<N; ++i){
        current = datetimes[i] ;
        current.erase(std::remove_if(current.begin(), current.end(), std::not1(std::ptr_fun(::isdigit))), current.end());
        date[i] = atoi(current.substr(0,8).c_str());
        time[i] = atoi(current.substr(8,12).c_str());
    }

    return List::create(_["date"]=date, _["time"]=time); 
}        

让我们测量一下:

> dates <- rep("2011-03-23T12:23:32.123", 1e+05)
> system.time(res1 <- datetimeToInt(dates))
    user  system elapsed
   0.081   0.006   0.087
> system.time(res2 <- datetimeToInt2(dates))
    user  system elapsed
   0.044   0.000   0.044
> identical(res1, res2)
[1] TRUE    
于 2013-06-19T10:58:29.153 回答
1

您可能想查看fasttimeSimon 的包(可在 rforge.net 上获得),它的功能非常相似。

它仅使用字符串操作而不使用日期解析来拆分假定为 UTC 时间的 ISO 日期时间字符串(尽管使用 'T' 分隔符)。我一直在使用它,因为它适合我在那里的需要。

请注意,您可能需要更仔细地考虑何时使用 STL 容器以及何时使用 Rcpp 容器。

最后,当您可以使用正确的日期类型时,不要使用字符串或 int 进行日期算术或比较——R、C++ 和 Rcpp 都有。

于 2013-06-19T13:15:32.633 回答