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

c2e8gylq  于 2023-02-10  发布在  其他
关注(0)|答案(1)|浏览(133)

这些是一些输入和相对期望输出

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::zipranges::views::zip_with对实现一般的transpose操作没有帮助,因为它们接受的参数数量是可变的(因此是在编译时已知的数),而transpose必须支持许多只有在运行时才知道的范围。原因在all3answersthis question中解释。

ecr0jaav

ecr0jaav1#

Eric Niebler在演示range-v3 https://www.youtube.com/watch?v=mFUXNMfaciE的演讲中实际实现了这个适配器的截断版本。
但它没有进入范围-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
要获得非截断版本,您可以修改复制粘贴的代码。

相关问题