我正在使用arma::find_unique
,我认为它返回了向量中每个唯一值首次出现的索引,但它似乎返回了其他内容。
这是一个玩具功能:
// [[Rcpp::export]]
arma::uvec test(arma::vec& x_) {
vec x=arma::sort(x_);
return arma::find_unique(x);
}
如果我使用简单向量test(5:1)
运行R中的函数,我会得到所有索引0,1,2,3,4
的向量,这是有意义的,因为每个值都是唯一的。
如果我尝试这样的话:
set.seed(1991)
var=sample(1:8,20,TRUE)
test(var)
输出:
1,3,6,7,19,12,14,18。
除了第一个值之外,所有这些值都是有意义的。为什么索引1处的第一个唯一值而不是0?很明显,我误解了arma::find_unique
打算做什么,所以如果有人能够启发我,我将不胜感激。
修改 我的会话信息
答案 0 :(得分:2)
好的,以下是@nrussell的礼貌,这个男人很棒,并在评论中给出了这个“答案”。 (我不配得到复选标记,也不值得赞成。)
实际上,我很确定这只是对Armadillo文档的误解,它从来没有真正保证使用稳定的排序,就像@Carl所期望的那样。在下面,std :: sort是
being called
,其中不能保证是C ++标准的稳定排序;还说here:“不保证保留相等元素的顺序。”
我可以演示这个here,复制犰狳算法中的"packet" structure用法。我的猜测是
libc++
(通常由OS X使用)确实将std::sort
实现为稳定排序,而libstdc++
则没有。{/ p>
轮到我:稳定排序,或维持具有相同键(即值)的记录的相对顺序,是这个问题背后的关键问题。例如,请考虑以下事项:
dog car pool dig
使用稳定排序按第一个字母排序可以得到:
car dog dig pool
因为“dog”这个词出现在向量中的“dig”之前,所以它必须出现在输出中的“dig”之前。
使用不稳定排序按第一个字母排序可以得到:
car dig dog pool
或
car dog dig pool
委托人与数字相关,因为每个密钥生成在字面上都存在于其他地方。所以,我们有:
2, 3, 2, 4
因此,当找到唯一值时:
2, 3, 4
2可以将id设为0或2.
正如@nrussell解释的那样,自OS X Mavericks(10.9)以来macOS默认依赖于--stdlib=libc++
与传统--stdlib=libstdc++
标志进行编译。这可能是我无法复制它的原因,因为一个实现选择稳定而另一个没有。
首先,我无法在macOS上复制这个...(见结束)
似乎我们能够在Linux上重现这个(@nrussel)。这意味着在某些时候,链接代码中存在问题。
其次,arma::find_unique使用here和matrix ops实施op_find_unique。后者是实现比较器的关键。
因此,简而言之,鉴于您对向量进行排序并且第一项始终被视为唯一,因此无法实现。
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::uvec test(arma::vec& x_) {
Rcpp::Rcout << "Input:" << x_.t() << std::endl;
arma::vec x = arma::sort(x_);
Rcpp::Rcout << "Sorted:" << x.t() << std::endl;
arma::uvec o = arma::find_unique(x);
Rcpp::Rcout << "Indices:" << o.t() << std::endl;
return o;
}
/*** R
set.seed(1991)
(v=sample(1:8,20,TRUE))
## [1] 2 2 1 5 7 6 7 6 4 1 5 3 1 4 4 2 8 7 7 8
sort(v)
## [1] 1 1 1 2 2 2 3 4 4 4 5 5 6 6 7 7 7 7 8 8
test(v)
### Received
## 2.0000 2.0000 1.0000 5.0000 7.0000 6.0000 7.0000 6.0000 4.0000 1.0000 5.0000 3.0000 1.0000 4.0000 4.0000 2.0000 8.0000 7.0000 7.0000 8.0000
### Sorted
## 1.0000 1.0000 1.0000 2.0000 2.0000 2.0000 3.0000 4.0000 4.0000 4.0000 5.0000 5.0000 6.0000 6.0000 7.0000 7.0000 7.0000 7.0000 8.0000 8.0000
### Output
## 0 3 6 7 10 12 14 18
*/