我得到了一个每行有两个元素的CSV文件:
1,2
12,40
11,7
...
我想把它读入std::map<int, int>
我怎么能做到这一点,使用任何从范围库和范围v3?
在这个答案的帮助下,我现在得到的是:
#include <boost/hof/lift.hpp>
#include <iostream>
#include <range/v3/istream_range.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/istream.hpp>
#include <range/v3/view/join.hpp>
#include <range/v3/view/chunk.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/split.hpp>
#include <string>
using ranges::istream;
using ranges::to;
using namespace ranges::views;
constexpr auto splitAtComma = [](auto const& r) { return r | split(','); };
constexpr auto rngToString = [](auto const& r) { return r | to<std::string>; };
constexpr auto strToInt = BOOST_HOF_LIFT(std::stoi);
constexpr auto parseCoords = transform(splitAtComma)
| join
| transform(rngToString)
| transform(strToInt)
| chunk(2);
int main() {
auto lines = istream<std::string>(std::cin);
auto coords = lines | parseCoords;
std::cout << coords << std::endl;
}
,像这样调用
./main <<END
1,2
12,40
11,7
END
给出如下输出
[[1,2],[12,40],[11,7]]
关键是现在我不知道如何将range-of-ranges转换成映射。此外,我有一种感觉,我在一条死胡同里,因为std::map<int, int>
的每个元素都来自2个int
s,但在[1,2]
,[12,40]
和[11,7]
以上的范围中,范围只是int
s的范围,而不是在编译时编码,只有2个int
s。
这里不需要使用join
,因为r | split(',')
已经为您提供了包含两个元素的范围。std::from_chars
优于std::stoi
。
你只能使用标准库的<ranges>
#include <ranges>
#include <charconv>
#include <fmt/ranges.h>
#include <sstream>
auto toInt = [](auto r) {
int i = 0;
std::from_chars(std::to_address(r.begin()), std::to_address(r.end()), i);
return i;
};
auto parseCoords =
std::views::transform(
[](auto r) { return std::move(r) | std::views::split(','); })
| std::views::transform(
[](auto r) { return std::pair{toInt(r.front()), toInt(*++r.begin())}; });
int main() {
auto in = std::istringstream{R"(
1,2
12,40
11,7
)"};
auto coords = std::views::istream<std::string>(in)
| parseCoords;
fmt::print("{}n", coords);
}
演示注意views::transform
中的std::move(r)
是必要的,因为我们需要构造一个owning_view
来避免悬空问题。