首页 > 解决方案 > Rcpp中字符串与单个值的向量化比较

问题描述

==在将数值向量与单个值进行比较时,Rcpp 中的运算符按预期工作。即向量的每个元素都与值进行比较,并返回一个逻辑向量。例如,考虑以下行为符合预期:

library(Rcpp)
cppFunction('
CharacterVector test_vals(NumericVector x) {
  if (is_true(any(x == 3))) return ("Values include 3");
  return ("3 not found");
}')
test_vals(1:2)
# [1] "3 not found"
test_vals(1:5)
# [1] "Values include 3"

但是,如果我尝试将字符向量与字符标量进行比较,它似乎只测试向量的第一个元素:

cppFunction('
CharacterVector test_names(NumericVector x) {
  CharacterVector y = x.attr("names");
  if (is_true(any(y == CharacterVector::create("foo")))) return ("Names include foo");
  return ("foo not found");
}')
test_names(c(a=1, b=2, foo=3))
# [1] "foo not found"
test_names(c(foo=3, a=1, b=2))
# [1] "Names include foo"

我知道比较两个相同长度的字符向量似乎以向量化的方式工作,正如预期的那样:

cppFunction('
CharacterVector test_names(NumericVector x) {
  CharacterVector y = x.attr("names");
  CharacterVector foo(x.size());
  foo.fill("foo");
  if (is_true(any(y == foo))) return ("Names include foo");
  return ("foo not found");
}')
test_names(c(a=1, b=2, foo=3))
# [1] "Names include foo"
test_names(c(foo=3, a=1, b=2))
# [1] "Names include foo"
test_names(c(a=1, b=2))
# [1] "foo not found"

这是否意味着字符向量与单个值的比较尚未实现Rcpp,或者我只是错过了如何做到这一点?

标签: rrcpp

解决方案


继续我们的快速讨论,这里有一个非常简单的解决方案,因为问题(如提出的那样)很简单——没有正则表达式,没有花哨。只需遍历所有元素并在找到匹配项后立即返回,否则使用false.

代码

#include <Rcpp.h>

// [[Rcpp::export]]
bool contains(std::vector<std::string> sv, std::string txt) {
    for (auto s: sv) {
        if (s == txt) return true;
    }
    return false;
}

/*** R
sv <- c("a", "b", "c")
contains(sv, "foo")
sv[2] <- "foo"
contains(sv, "foo")
*/

演示

> Rcpp::sourceCpp("~/git/stackoverflow/66895973/answer.cpp")

> sv <- c("a", "b", "c")

> contains(sv, "foo")
[1] FALSE

> sv[2] <- "foo"

> contains(sv, "foo")
[1] TRUE
> 

这实际上只是在寻找我们可能已经在(大约)100k 行 Rcpp 中已经拥有的东西,或者 STL 可能拥有的东西之前从臀部拍摄......

这同样适用于您之前的命名属性示例,当然,您可以使用CharacterVector, 和/或使用从它到std::vector<std::string>我们在此处使用的转换,或者...如果您有较旧的编译器,请切换forfrom C++11 风格到 K+R 风格。


推荐阅读