2016-07-25 1 views
0

Мои извинения за очень основной вопрос, я новичок в Rcpp и C++ из R.Нахождение индекса строки внутри поля строк

У меня есть поле (arma::field), который я инициализируется держать нити (arma::field<std::string> my_vector). У меня также есть строка std::string id, которая находится где-то внутри поля строк, и мне хотелось бы найти позицию, где она находится. Я привык делать это с помощью векторов и чисел похожи на ниже:

arma::vec fun(arma::vec input_vector){ 

    // Find where vector equals 5 (for example) 
    uvec index = arma::find(input_vector == 5); 

    return index; 
} 

Первоначально я пытался сделать то же самое, но, учитывая строку вместо числа для сравнения:

arma::uvec fun(arma::vec input_vector, std::string id){ 

    // Find where vector string id 
    uvec index = arma::find(input_vector == id); 

    return index; 
} 

Это возвращает ошибку

error: invalid operands to binary expression ('arma::vec' (aka 'Col<double>') 
    and 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')) 

, который имеет смысл, так как вектор не был инициализирован содержать строки. Хотя я не думаю, что вектор может быть инициализирован, чтобы содержать строки, потому что когда я попытался arma::vec<std::string>, это дает беспорядок ошибок.

Это приведет меня к полям, которые могут содержать намного больше видов переменных.

arma::uvec fun(arma::field<std::string> input_field, std::string id){ 

    // Find where vector equals 5 (for example) 
    uvec index = arma::find(input_field == id); 

    return index; 
} 

Однако это возвращает

error: invalid operands to binary expression ('arma::field<std::string>' and 
     'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')) 

Я попытался strcmp, а также, который также бросил ошибку

error: no viable conversion from 'arma::field<std::string>' to 'const char *' 

Это приводит меня спросить, как я могу найти положение строка внутри поля?

Я открыт для изменения типов вокруг чего-то, что работает лучше, я подозреваю, что использование std::vector может работать лучше или, возможно, другого типа, о котором я не слышал. Однако мои первые эксперименты не были очень успешными. Если у кого-то есть какие-то намеки, в каком направлении идти, это было бы очень признательно.

Edit: Уточнено, что find был arma::find вместо std::find, как это было очень не понятно.

ответ

3

arma не поддерживает хранение std::string в своих структурах данных за Matrix types

Класс корневая матрица является Mat, где тип один из:

  • поплавка, двойной, станд :: сложный, std :: complex, short, int, long и unsigned версии short, int, long

В свою очередь, Rcpp не поддерживает импорт или экспорт std::vector<std::string> в armadillo. Таким образом, ошибка.

Самый простой способ найти строку в этом случае - это пропустить вектор и проверить каждый элемент. Кроме того, сделайте карту и посмотрите, находится ли ключ в пределах карты.

строка Loop проверки подход:

#include <Rcpp.h> 

// [[Rcpp::export]] 
std::vector<int> find_string_locs(std::vector<std::string> input_vector, std::string id) 
{ 
    std::vector<int> id_locs; // Setup storage for found IDs 

    for(int i =0; i < input_vector.size(); i++) // Loop through input 
    if(input_vector[i] == id) // check if input matches target 
     id_locs.push_back(i); 

    return id_locs; // send locations to R (c++ index shift!) 
} 

/***R 
input_vector = c("stat","toad","stat","rcpp") 
id = "stat" 
find_string_locs(input_vector,id) 
*/ 

Выход затем:

[1] 0 2 

Примечание C++ индекс сдвига ... начинается с 0, а не 1, как в R.

+0

Спасибо за совет. Эта часть кода находится в пределах приличного размера, поэтому, хотя цикл через каждый элемент определенно звучит как жизнеспособное решение, хотя, вероятно, и не в этом случае. Я рассмотрю идею ключа/карты. Всего наилучшего. –

+0

@ChrisC Я рассмотрю это позже сегодня с примером кода. Кроме того, циклы на C++ являются ** не ** злыми. – coatless

+0

Цените помощь @Coatless. Не торопитесь, я уверен, что вы очень заняты своими делами. –

0

В дополнение к тому, что сказал Коатлесс, я не уверен, вы понимаете использование вектора на C++. В C++ вектор - просто переизмеримый список.

Что касается векторов алгебры, то она имеет величину (размер), но на самом деле она не имеет никакого направления. Другими словами, это не вектор в алгебраическом смысле.

Если вы хотите искать зЬй :: вектор для строки, вы можете сделать это так:

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 

int get_str_position(const std::string& str_to_find, const std::vector<std::string>& vector_to_search) 
{ 
    std::vector<std::string>::const_iterator it = std::find(vector_to_search.begin(), vector_to_search.end(), str_to_find); 

    if (it == vector_to_search.end()) { 
     return -1; 
    } 
    else { 
     return it - vector_to_search.begin(); 
    } 
}; 

void find_str(const std::string& str_to_find, const std::vector<std::string>& vector_to_search) 
{ 
    int position = get_str_position(str_to_find, vector_to_search); 

    if (position == -1) { 
     std::cout << "Could not find string: '" << str_to_find << "'" << std::endl; 
    } 
    else { 
     std::cout << "Found string '" << str_to_find << "' at position " << position << std::endl; 
    } 
}; 

int main() 
{ 

    std::vector<std::string> vec = { "one", "two", "three" }; 

    std::string existent_str = "two"; 
    std::string non_existent_str = "four"; 

    find_str(existent_str, vec); 
    find_str(non_existent_str, vec); 

    return 0; 
} 

Возвращает:

Found string 'two' at position 1 
Could not find string: 'four' 

Далее, в «удовольствие» вашей функции , вы говорите:

arma::uvec fun(arma::field<std::string> input_field, std::string id){ 

    // Find where vector equals 5 (for example) 
    uvec index = find(input_field == id); 

    return index; 
} 

Если вы используете зЬй :: найти, вы будете искать только «input_field» для значения 0 или 1, с ince вы проходите логическое выражение в качестве аргумента, чтобы найти ...

// Not sure how this works at all 
// You should not be able to compare a string to a std::vector<std::string> 
bool true_or_false = (input_field == id); 


// Find 0 (false) or 1 (true) 
uvec index = find(true_or_false); 
+1

Спасибо, Винсент, ты совершенно прав, я действительно не понимаю С ++! Большое вам спасибо за код и усилия, которые вы вложили в него, я присмотрюсь и попытаюсь реализовать его самостоятельно. Хотя невозможно, чтобы вы знали это, функция 'find' была фактически' arma :: find' в отличие от 'std :: find'. Это все еще не делает то, что я сделал, но, возможно, проливает некоторый свет на логику. Независимо от того, спасибо за вашу помощь, это было очень полезно. –

+1

OP использует http://arma.sourceforge.net/docs.html#find not 'std :: find' – coatless

Смежные вопросы