Я пользователь R и изучаю C++ для использования в Rcpp. Недавно я написал альтернативу R's strsplit
в Rcpp, используя string.h
, но не на основе regex (afaik). Я читал о Boost и нашел sregex_token_iterator.Rcpp - Захват результата sregex_token_iterator в вектор
На сайте ниже есть пример:
std::string input("This is his face");
sregex re = sregex::compile(" "); // find white space
// iterate over all non-white space in the input. Note the -1 below:
sregex_token_iterator begin(input.begin(), input.end(), re, -1), end;
// write all the words to std::cout
std::ostream_iterator<std::string> out_iter(std::cout, "\n");
std::copy(begin, end, out_iter);
Моя rcpp
функция работает просто отлично:
#include <Rcpp.h>
#include <boost/xpressive/xpressive.hpp>
using namespace Rcpp;
// [[Rcpp::export]]
StringVector testMe(std::string input,std::string uregex) {
boost::xpressive::sregex re = boost::xpressive::sregex::compile(uregex); // find a date
// iterate over the days, months and years in the input
boost::xpressive::sregex_token_iterator begin(input.begin(), input.end(), re ,-1), end;
// write all the words to std::cout
std::ostream_iterator<std::string> out_iter(std::cout, "\n");
std::copy(begin, end, out_iter);
return("Done");
}
/*** R
testMe("This is a funny sentence"," ")
*/
Но все это делает печать из маркеров. Я очень новичок в C++, но я понимаю идею создания вектора в rcpp
с StringVector res(10);
(сделайте вектор с именем res длиной 10), который я могу затем проиндексировать res[1] = "blah"
.
Мой вопрос: как взять вывод boost::xpressive::sregex_token_iterator begin(input.begin(), input.end(), re ,-1), end;
и сохранить его в векторе, чтобы я мог его вернуть?
Окончательного рабочий Rcpp решение
В том числе это потому, что моя потребность была Rcpp специфична и я должен был сделать некоторые незначительные изменения в раствор при условии.
#include <Rcpp.h>
#include <boost/xpressive/xpressive.hpp>
typedef std::vector<std::string> StringVector;
using boost::xpressive::sregex;
using boost::xpressive::sregex_token_iterator;
using Rcpp::List;
void tokenWorker(/*in*/ const std::string& input,
/*in*/ const sregex re,
/*inout*/ StringVector& v)
{
sregex_token_iterator begin(input.begin(), input.end(), re ,-1), end;
// write all the words to v
std::copy(begin, end, std::back_inserter(v));
}
//[[Rcpp::export]]
List tokenize(StringVector t, std::string tok = " "){
List final_res(t.size());
sregex re = sregex::compile(tok);
for(int z=0;z<t.size();z++){
std::string x = "";
for(int y=0;y<t[z].size();y++){
x += t[z][y];
}
StringVector v;
tokenWorker(x, re, v);
final_res[z] = v;
}
return(final_res);
}
/*** R
tokenize("Please tokenize this sentence")
*/
Вы можете просто использовать 'back_inserter' на' 'вектор и вызвать' Rcpp :: wrap' на результат; например 'std :: vector результат; std :: copy (начало, конец, std :: back_inserter (результат)); return Rcpp :: wrap (result); '. –
nrussell
@Mark Эта функция 'tokenize' требует перезаписи.Конкатенации строк, которые у вас уже есть, бессмысленны, и вам даже не нужна эта «х» копия; u создайте бесполезные копии t и v, и итерация с индексом 'z' вместо' const iterator' здесь по крайней мере сомнительна, потому что вы используете ее только для разыменования. –