首页 > 解决方案 > 如何使用 Range-v3 在 C++ 中模拟 Haskell 的 Data.List.transpose?

问题描述

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

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必须支持多个范围仅在运行时知道。这个问题的所有 3 个 答案都解释了原因。

标签: c++haskellfunctional-programmingtransposerange-v3

解决方案


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/aWhWfzEdq

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


推荐阅读