代码之家  ›  专栏  ›  技术社区  ›  Caduchon

检查std::set中包含的所有三个不同值?

  •  0
  • Caduchon  · 技术社区  · 7 年前

    for(std::size_t i = 0; i < data.size(); ++i)
      for(std::size_t j = i+1; j < data.size(); ++j)
        for(std::size_t k = j+1; k < data.size(); ++k)
          do_somthing_with(data[i],data[j],data[k]);
    

    如果我的容器是一个 std::set ?

    5 回复  |  直到 7 年前
        1
  •  1
  •   paler123    7 年前

    您可以执行与向量大致相同的操作,但需要创建一个包装器函数,该函数将复制并递增集合迭代器:

    std::set<int>::const_iterator next_iterator(std::set<int>::const_iterator it)
    {
      return ++it; // it has been passed by value, so already copied
    }
    
    //...
    
    for (std::set<int>::const_iterator it = data.begin(); it != data.end(); ++it)
      for(std::set<int>::const_iterator jt = next_iterator(it); jt != data.end(); ++jt)
        for(std::set<int>::const_iterator kt = next_iterator(jt); kt != data.end(); ++kt)
           // ...
    
        2
  •  1
  •   Jarod42    7 年前

    你可以这样做:

    if (data.size() < 2) { return; }
    
    for (auto it1 = data.begin(); it1 != std::prev(data.end(), 2); ++it1) {
        for (std::size_t it2 = std::next(it1); it2 != std::prev(data.end()); ++it2) {
          for (std::size_t it3 = std::next(it2); it3 != data.end(); ++it3) {
              do_something_with(*it1, *it2, *it3);
          }
       }
    }
    

    您可以缓存 std::prev

        3
  •  0
  •   hassec    7 年前

    这是从一组n个元素中选择所有k个组合的特例。

    请参见此处以获取解释: https://en.wikipedia.org/wiki/Combination

    这已经在stackoverflow上得到了回答: creating all possible k combinations of n items in C++

        4
  •  0
  •   vdavid    7 年前

    在向量示例中,您可以将您的问题想象为必须对索引使用迭代器。让我们简化一下:

    for(std::size_t i = 0; i < data.size(); ++i)
      do_somthing_with(data[i]);
    

    你可以用迭代器这样写:

    for(std::vector<MyClass>::iterator it = data.begin(); it != data.end(); ++it)
      do_somthing_with(*it);
    

    现在可以直接对集合执行相同的操作:

    for(std::set<MyClass>::iterator it = data.begin(); it != data.end(); ++it)
      do_somthing_with(*it);
    

    如果您想使用三重循环,在我看来,问题是从下一个迭代器开始的。用C++ 11可以使用 std::next

    for(std::set<MyClass>::iterator it1 = data.begin(); it1 != data.end(); ++it1)
    {
      std::set<MyClass>::iterator it2 = it1;
      ++it2;
      for(; it2 != data.end(); ++it2)
      {
        std::set<MyClass>::iterator it3 = it2;
        ++it3;
        for(; it3 != data.end(); ++it3)
          do_somthing_with(*it1,*it2,*it3);
      }
    }
    

    或者你可以定义你自己的 next

    template<class ForwardIt>
    ForwardIt next(ForwardIt it)
    {
        return ++it;
    }
    

    这基本上是 suggested implementation of std::next

    这样代码就可以更容易地重写:

    for(std::set<MyClass>::iterator it1 = data.begin(); it1 != data.end(); ++it1)
      for(std::set<MyClass>::iterator it2 = next(it1); it2 != data.end(); ++it2)
        for(std::set<MyClass>::iterator it3 = next(it2); it3 != data.end(); ++it3)
          do_somthing_with(*it1,*it2,*it3);
    
        5
  •  -1
  •   Jim Nilsson    7 年前

    你可以从中创建一个向量,然后按照你通常的方式来做。

    std::set<int> s = {1, 2, 3, 4, 5, 6, 7};
    std::vector<int> data(s.begin(), s.end());
    for(std::size_t i = 0; i < data.size(); ++i)
      for(std::size_t j = i+1; j < data.size(); ++j)
        for(std::size_t k = j+1; k < data.size(); ++k)
          do_somthing_with(data[i],data[j],data[k]);