【问题标题】:How to loop std::set with custom .begin() and .end()?如何使用自定义 .begin() 和 .end() 循环 std::set?
【发布时间】:2015-01-15 07:05:13
【问题描述】:

如果我有一套例如,内容如下:0,1,2,3,8,13,56,532,

我将如何处理从 3 到 532 到 0 到 3 的 for(auto it = xxxxx; y ? z; ++it)

喜欢:

magic.start(3);
for(auto i: magic)
    std::cout << i << " ";

那会打印出来:

3 8 13 56 532 0 1 2

编辑:可能有人对最终结果感兴趣(感谢所有答案):

bool SpectateNextPlayer(int playerid)
{
    if (PlayerCurrentlySpectating[playerid] == INVALID_PLAYER_ID)
        return false;

    auto current = PlayersOnline.find(PlayerCurrentlySpectating[playerid]);

    for (auto it = current; it != PlayersOnline.end(); ++it)
        if (PlayerSpactatable(*it) && (*it) != PlayerCurrentlySpectating[playerid])
            if (PlayerSpectateOtherPlayer(playerid, *it))//check here if playerid != *it
                return true;

    for (auto it = PlayersOnline.begin(); it != current; ++it)
        if (PlayerSpactatable(*it) && (*it) != PlayerCurrentlySpectating[playerid])
            if (PlayerSpectateOtherPlayer(playerid, *it))
                return true;

    return !DisablePlayerSpectate(playerid);
}

bool SpectatePreviousPlayer(int playerid)
{   
    if (PlayerCurrentlySpectating[playerid] == INVALID_PLAYER_ID)
        return false;

    auto rcurrent = find(PlayersOnline.rbegin(), PlayersOnline.rend(), PlayerCurrentlySpectating[playerid]);

    for (auto it = rcurrent; it != PlayersOnline.rend(); ++it)
        if (PlayerSpactatable(*it) && (*it) != PlayerCurrentlySpectating[playerid])
            if (PlayerSpectateOtherPlayer(playerid, *it))
                return true;

    for (auto it = PlayersOnline.rbegin(); it != rcurrent; ++it)
        if (PlayerSpactatable(*it) && (*it) != PlayerCurrentlySpectating[playerid])
            if (PlayerSpectateOtherPlayer(playerid, *it))
                return true;

    return !DisablePlayerSpectate(playerid);
}

【问题讨论】:

  • 为什么不能使用两个循环
  • 好吧,我想如果没有其他方法也没关系 :) 但是我在使用 for (auto it = PlayersOnline.end(); it != PlayersOnline.find(3); --it) 反向执行此操作时遇到问题,因为这会崩溃。
  • 如果您需要保存结果序列,您可以使用rotate_copy 和附加容器。但是如果你只是想遍历集合,这个解决方案可能效率低下。

标签: c++ for-loop set


【解决方案1】:

你可以这样做(有两个循环)。

代码使用set::find() 来追踪您希望从哪个元素开始。然后它将从 find() 返回的迭代器中打印,直到集合结束。请注意,为简单起见,我没有检查 find() 返回的内容。

在第二个循环中,它将从头开始打印,直到遇到第一个循环开始的元素。

#include <iostream>
#include <set>

int main ()
{
  std::set<int> myset;
  myset.insert (0);
  myset.insert (1);
  myset.insert (2);
  myset.insert (3);
  myset.insert (8);
  myset.insert (13);
  myset.insert (56);
  myset.insert (532);

    std::cout << "myset contains:";
    std::set<int>::iterator it1;
    it1=myset.find(3);
    for (std::set<int>::iterator it = it1; it!=myset.end(); ++it)
      std::cout << ' ' << *it;
    std::cout << '\n';

    for (std::set<int>::iterator it2=myset.begin(); *it2!=*it1; ++it2)
      std::cout << ' ' << *it2;
    std::cout << '\n';


  return 0;
}

输出:

myset contains: 3 8 13 56 532
 0 1 2

为了向后执行此操作,您可以在this 回答中执行类似操作。

【讨论】:

  • 是的@Gizmo,你只需要从.end() - 1开始。要我给你举个例子吗?或者你可以从这里处理它? ;)
【解决方案2】:
auto i = magic.find(3);
if (i != magic.end())
{
    auto finito = i;
    do
    {
        std::cout << *i << ' '; // or whatever you want to do with elements
        if (++i == magic.end()) i = magic.begin();
    } while (i != finito);
}

【讨论】:

    【解决方案3】:

    我猜你的意思是这样的:

    bool first=true;
    auto start = magic.find(3);
    for(auto it=start;it!=start || first;it++){
       first = false;
       if(it == magic.end()){//make it like a circled list
         it = magic.begin();
       }
       if(it == magic.end()){
           cout << *it;
       } 
    }
    

    【讨论】:

    • 您的代码很好,也可以工作,虽然它引入了一个额外的变量,并且需要阅读我的代码的人来分析这个片段,所以 +1 以获得好的答案,但我会选择上面的:#
    猜你喜欢
    • 2012-12-04
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多