查找字符串

时间:2016-07-25 15:22:11

标签: c++ r rcpp armadillo

我为一个非常基本的问题道歉,我是来自R的Rcpp和c ++的新手。

我有一个字段(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可能会更好或者可能是另一种我没有听说过的方式。但是,我的第一次实验并不是很成功。如果有人对哪个方向有任何提示,我将不胜感激。

修改:澄清findarma::find而不是std::find,因为它非常不清楚。

2 个答案:

答案 0 :(得分:3)

arma不支持在每个Matrix types的数据结构中存储std::string

  

根矩阵类是Mat,其中type是以下之一:

     
      
  • float,double,std :: complex,std :: complex,short,int,long和unsigned版本的short,int,long
  •   

反过来,Rcpp不支持将std::vector<std::string>导入或导出到armadillo。因此,错误。

在这种情况下,查找字符串的最简单方法是遍历向量并检查每个元素。或者,制作地图并查看该键是否在地图内。

循环字符串检查方法:

#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 ++索引转换...从R开始,而不是像R中的那样。

答案 1 :(得分:0)

除了Coatless所说的,我不确定,你了解在C ++中使用向量。在C ++中,向量只是一个可调整大小的列表。

关于代数矢量,它具有幅度(大小)但它实际上没有方向。换句话说,它不是代数意义上的向量。

如果您想在std :: vector中搜索字符串,可以这样做:

#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;
}

如果您正在使用std :: find,那么您只会在'input_field'中搜索0或1的值,因为您将布尔表达式作为参数传递给find ...

// 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);