如何将2个列CSV文件读取到带有范围的地图中?

发布于 2025-02-06 15:17:12 字数 2147 浏览 1 评论 0 原文

我给了一个CSV文件,每行两个元素:

1,2
12,40
11,7
...

我想将其阅读到 std :: map&lt< int,int> 中。

我该怎么做,使用 ranges library range-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]]

要点是,现在我不知道如何将该范围转换为地图。另外,我感觉自己在一条死胡同,因为 std :: map&lt&lt; int,int&gt; 的每个元素来自2 int s ,但是在上面的范围 [1,2] [12,40] [11,7] 是只是 int s的范围,而不是在compile tiime上编码2 int s。

I'm given a CSV file with two elements per line:

1,2
12,40
11,7
...

which I want to read into a std::map<int, int>.

How can I do that, using anything from Ranges library and Range-v3?

At the moment this is where I've got (with the help of this answer):

#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;
}

which, invoked like this

./main <<END
1,2
12,40
11,7
END

gives this output

[[1,2],[12,40],[11,7]]

The point is that now I don't know how convert that range-of-ranges into a map. Also, I have the feeling that I'm in a dead-end street, because each element of a std::map<int, int> comes from 2 ints, but in the range-of-ranges above [1,2], [12,40], and [11,7] are just ranges of ints, not encoding at compile tiime that there's 2 ints only.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

哑剧 2025-02-13 15:17:12

无需在此处使用加入,因为 r | split(',')已经为您提供了带有两个元素的范围。优先 std :: From_chars 而不是 std :: Stoi

您只能使用标准库的&lt; ranges&gt;

#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);
}

demo

注意 std :: move(r) in views :: transform 是必要的,因为我们需要构造 oning_view 以避免悬而未决的问题。

There is no need to use join here because r | split(',') already gives you a range with two elements. Prefer std::from_chars over std::stoi.

You can do this only using the standard library's <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);
}

Demo

Note that the std::move(r) in views::transform is necessary because we need to construct an owning_view to avoid the dangling issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文