我有一个python函数,它在许多输入数组的笛卡尔积中返回第n个元素
def prod(n, arrs):
out = []
for i,arr in enumerate(arrs):
denom = numpy.prod([ len(p) for p in arrs[i+1:] ], dtype=int)
idx = n // denom % len(arr)
out.append( arr[idx] )
return out
这很好用:
a = [ 1000, 1100, 1200, 1300, 1400 ]
b = [ 1.0, 1.5, 2.0, 2.5, 3.0, 3.5 ]
c = [ -2, -1, 0, 1, 2 ]
for n in range(20, 30):
i = prod(n, [a, b, c])
print(n, i)
[1000, 3.0, -2] [1000, 3.0, -1] [1000, 3.0, 0] [1000, 3.0, 1] [1000, 3.0, 2] [1000, 3.5, -2] [1000, 3.5, -1] [1000, 3.5, 0] [1000, 3.5, 1] [1000, 3.5, 2]
现在我想将其翻译为C ++(最高标准C ++-17)
template<typename... Ts>
auto prod(std::size_t n, const std::vector<Ts>&... vs)
-> std::tuple<const std::decay_t<typename std::vector<Ts>::value_type>&...>
{
// template magic here
}
有人可以帮助我使用上述公式构造元组所需的模板魔术吗?
其他答案已经提到了索引技巧。这是我的尝试,请尽可能直接从您的python代码进行转换:
template <typename T, std::size_t... I>
auto prod_impl(std::size_t n, T tuple, std::index_sequence<I...>) {
std::array sizes{ std::size(std::get<I>(tuple))... };
auto enumerator = [&sizes,n](std::size_t i, auto&& arr) -> decltype(auto) {
auto denom = std::accumulate(std::begin(sizes) + i + 1, std::end(sizes), 1, std::multiplies<>{});
auto idx = (n / denom) % std::size(arr);
return arr[idx];
};
return std::forward_as_tuple(enumerator(I, std::get<I>(tuple))...);
}
template<typename... Ts, typename Is = std::index_sequence_for<Ts...>>
auto prod(std::size_t n, const std::vector<Ts>&... vs) {
return prod_impl(n, std::forward_as_tuple(vs...), Is{});
}
(实时示例:http : //coliru.stacked-crooked.com/a/a8b975c29d429054)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句