我对this question采取了后续行动。在Add-Type -AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.FileIO.FileSystem]::Deletedirectory('e:\test\testfolder','OnlyErrorDialogs','SendToRecycleBin')
中,您可以在辅助密钥后订购重复项。我怎样才能在R
中实现这一目标?我正在尝试以下内容(灵感来自Kevin Ushey对原始问题的回答),这似乎适用于简单的情况。我怎么能概括这个?
Rcpp
答案 0 :(得分:3)
如果我理解你的要求,一种方法就是利用comparison operators of std::tuple
,这应该"做正确的事情"。
// [[Rcpp::plugins(cpp11)]]
#include <Rcpp.h>
#include <tuple>
template <typename... Ts>
struct Point {
std::size_t index;
using tuple_t = std::tuple<Ts...>;
tuple_t data;
template <typename... Vs>
Point(std::size_t i, const Vs&... vs)
: index(i),
data(std::forward<decltype(vs[i])>(vs[i])...)
{}
bool operator<(const Point& other) const {
return data < other.data;
}
};
template <typename... Ts>
class PointVector {
public:
std::size_t sz;
using vector_t = std::vector<Point<Ts...>>;
vector_t data;
template <typename... Vs>
PointVector(const Vs&... vs)
: sz(min_size(vs...))
{
data.reserve(sz);
for (std::size_t i = 0; i < sz; i++) {
data.emplace_back(i, vs...);
}
}
Rcpp::IntegerVector sorted_index() const {
vector_t tmp(data);
std::stable_sort(tmp.begin(), tmp.end());
Rcpp::IntegerVector res(sz);
for (std::size_t i = 0; i < sz; i++) {
res[i] = tmp[i].index + 1;
}
return res;
}
private:
template <typename V>
std::size_t min_size(const V& v) {
return v.size();
}
template <typename T, typename S, typename... Vs>
std::size_t min_size(const T& t, const S& s, const Vs&... vs) {
return t.size() < s.size() ?
min_size(t, vs...) :
min_size(s, vs...);
}
};
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector order2(NumericVector x, NumericVector y) {
PointVector<double, double> pv(x, y);
return pv.sorted_index();
}
// [[Rcpp::export]]
IntegerVector order3(NumericVector x, NumericVector y, NumericVector z) {
PointVector<double, double, double> pv(x, y, z);
return pv.sorted_index();
}
使用此数据进行演示,
x <- rep(1:2 + 0.5, 10)
y <- rep(1:4 + 0.5, 5)
z <- rep(1:5 + 0.5, 4)
(df <- data.frame(x, y, z))
# x y z
# 1 1.5 1.5 1.5
# 2 2.5 2.5 2.5
# 3 1.5 3.5 3.5
# 4 2.5 4.5 4.5
# 5 1.5 1.5 5.5
# 6 2.5 2.5 1.5
# 7 1.5 3.5 2.5
# 8 2.5 4.5 3.5
# 9 1.5 1.5 4.5
# 10 2.5 2.5 5.5
# 11 1.5 3.5 1.5
# 12 2.5 4.5 2.5
# 13 1.5 1.5 3.5
# 14 2.5 2.5 4.5
# 15 1.5 3.5 5.5
# 16 2.5 4.5 1.5
# 17 1.5 1.5 2.5
# 18 2.5 2.5 3.5
# 19 1.5 3.5 4.5
# 20 2.5 4.5 5.5
C ++版本产生与基本R等价物相同的结果:
all.equal(base::order(x, y, z), order3(x, y, z))
# [1] TRUE
df[order3(x, y, z),]
# x y z
# 1 1.5 1.5 1.5
# 17 1.5 1.5 2.5
# 13 1.5 1.5 3.5
# 9 1.5 1.5 4.5
# 5 1.5 1.5 5.5
# 11 1.5 3.5 1.5
# 7 1.5 3.5 2.5
# 3 1.5 3.5 3.5
# 19 1.5 3.5 4.5
# 15 1.5 3.5 5.5
# 6 2.5 2.5 1.5
# 2 2.5 2.5 2.5
# 18 2.5 2.5 3.5
# 14 2.5 2.5 4.5
# 10 2.5 2.5 5.5
# 16 2.5 4.5 1.5
# 12 2.5 4.5 2.5
# 8 2.5 4.5 3.5
# 4 2.5 4.5 4.5
# 20 2.5 4.5 5.5
修改:这是一个稍微更可口的版本,它允许您编写auto pv = MakePointVector(...)
而不是指定所有类型参数:
// Point class as before
template <typename... Vecs>
class PointVector {
public:
std::size_t sz;
using point_t = Point<typename std::remove_reference<decltype(Vecs{}[0])>::type...>;
using vector_t = std::vector<point_t>;
vector_t data;
template <typename... Vs>
PointVector(const Vecs&... vs)
: sz(min_size(vs...))
{
data.reserve(sz);
for (std::size_t i = 0; i < sz; i++) {
data.emplace_back(i, vs...);
}
}
Rcpp::IntegerVector sorted_index() const {
vector_t tmp(data);
std::stable_sort(tmp.begin(), tmp.end());
Rcpp::IntegerVector res(sz);
for (std::size_t i = 0; i < sz; i++) {
res[i] = tmp[i].index + 1;
}
return res;
}
private:
template <typename V>
std::size_t min_size(const V& v) {
return v.size();
}
template <typename T, typename S, typename... Vs>
std::size_t min_size(const T& t, const S& s, const Vs&... vs) {
return t.size() < s.size() ?
min_size(t, vs...) :
min_size(s, vs...);
}
};
template <typename... Vecs>
PointVector<Vecs...> MakePointVector(const Vecs&... vecs) {
return PointVector<Vecs...>(vecs...);
}
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector order2(NumericVector x, NumericVector y) {
auto pv = MakePointVector(x, y);
return pv.sorted_index();
}
// [[Rcpp::export]]
IntegerVector order3(NumericVector x, NumericVector y, NumericVector z) {
auto pv = MakePointVector(x, y, z);
return pv.sorted_index();
}
/*** R
all.equal(base::order(x, y), order2(x, y))
# [1] TRUE
all.equal(base::order(x, y, z), order3(x, y, z))
# [1] TRUE
*/