如何在C++中使用Range-v3模拟Haskell的Data.List.transpose?

4

这些是一些输入和相关的期望输出

std::vector<std::string> v1{"aeiou", "bcdfghjk"};
std::vector<std::string> v2{"aeiou", "bcd"};
auto w1 = v1 | wanne_be_transpose;
auto w2 = v2 | wanne_be_transpose;
// w1 = {"ab","ec","id","of","ug","h","j","k"}
// w2 = {"ab","ec","id","o","u"}

说实话,我不知道如何使用范围进行仿真。(在一般情况下,如果v1.size() > 2,我就更不懂了,但我的用例本质上是v1.size() == 2,所以我只需要解决这种情况的问题。)
最初,我认为可以使用ranges::views::zip将它们组合在一起,然后将成对的元素转换为内部范围,但这样行不通,因为zip的输出与最短序列一样长。
在Haskell中有Data.List.transpose
λ> Data.List.transpose $ ["aeiou","bcdfghjk"]
["ab","ec","id","of","ug","h","j","k"]
λ> Data.List.transpose $ ["aeiou","bcd"]
["ab","ec","id","o","u"]

经过一段时间之后回来看这个问题,我认为可以说 ranges::views::zip或者ranges::views::zip_with在实现通用的transpose操作时没有帮助。因为它们采用可变数量的参数(也就是编译时已知的数量),而transpose必须支持在运行时才知道的多个范围。这个原因在这个问题三个回答都有解释。


你等着要一个 zip_longest 适配器吗?https://github.com/ericniebler/range-v3/issues/1667 - Tom Huntington
1
@TomHuntington,如果要像zip/zip_with一样实现zip_longest,即它接受可变数量的参数,那么它只能在某种程度上帮助。例如,在转置range<range<T>>的情况下,其中外部范围的长度在编译时已知(我的示例,但在将v1v2更改为std::arrays<T,2>之前);但在其他情况下,它将无济于事。 - Enlico
1个回答

1

Eric Niebler实际上为他的演示range-v3实现了这个适配器的截断版本https://www.youtube.com/watch?v=mFUXNMfaciE

但它没有进入range-v3 https://github.com/ericniebler/range-v3/issues/776

然而,从https://github.com/ericniebler/range-v3/blob/master/example/calendar.cpp复制粘贴,我们可以这样做

std::vector<std::string> v1{ "aeiou", "bcdfghjk" };
print2D(v1 | transpose());

https://godbolt.org/z/vj6bbsWso

要获取非截断版本,您可以修改复制粘贴的代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接