【问题标题】:List<> Get Next element or get the firstList<> 获取下一个元素或获取第一个
【发布时间】:2009-04-22 11:20:59
【问题描述】:

我想获取列表中的下一个元素,如果列表在其末尾,我想要第一个元素。 换句话说,我只想让它循环。

   List<int> agents = taskdal.GetOfficeAgents(Branches.aarhusBranch);
    if (lastAgentIDAarhus != -1)
    {
        int index = agents.IndexOf(lastAgentIDAarhus);
        if (agents.Count > index + 1)
        {
            lastAgentIDAarhus = agents[index + 1];
        }
        else
        {
            lastAgentIDAarhus = agents[0];
        }
    }
    else
    {
        lastAgentIDAarhus = agents[0];
    }

我对上面显示的我自己的解决方案相当不满意,如果你有更好的解决方案,请告诉我:)

【问题讨论】:

    标签: c#


    【解决方案1】:
    lastAgentIDAarhus = agents[index == -1 ? 0 : index % agents.Count];
    

    MOD 运算符 % 的使用自动将索引切分到可能索引的范围内。

    模运算符是对 DIV (/) 运算符的补充,它返回两个整数相除的余数。例如,如果您将 9 除以 6,则结果为 1,余数为 3。MOD 运算符要求 3。

    【讨论】:

    • 哇,如果可行的话,这是一个非常简洁的解决方案:) 愿意解释一下吗?
    • mod 运算符进行模运算,这正是您想要的。如果您可以将索引初始化为 0 而不是 -1,您可以使用:lastAgentIDAarhus = agent[index % (agents.Count - 1)]
    • 我觉得应该是index % ( agents.Count )
    • @EricYin:您的 Count 将始终比您拥有的最高索引高 1。这是因为(通常)索引从 0 开始,而 Count 属性从 1 开始。
    • @EricYin 是正确的。假设您有一个包含 10 个项目的列表,并且您尝试访问索引 10 处的项目(它不存在)。 10%10=0 是你想要的,而不是 10%9=1。
    【解决方案2】:

    或者简单地说:

    public static T NextOf<T>(this IList<T> list, T item)
    {
        var indexOf = list.IndexOf(item);
        return list[indexOf == list.Count - 1 ? 0 : indexOf + 1];
    }
    

    例子:

    List<string> names = new List<string>();
    
    names.Add("jonh");
    names.Add("mary");
    
    string name = String.Empty;    
    
    name = names.NextOf(null);   //name == jonh
    
    name = names.NextOf("jonh"); //name == mary
    
    name = names.NextOf("mary"); //name == jonh
    

    【讨论】:

      【解决方案3】:

      作为对此略有不同的看法,这里有一个扩展方法,您可以使用它来使任何 IEnumerable '循环'

        public static IEnumerable<T> AsCircularEnumerable<T>(this IEnumerable<T> enumerable)
        {
          var enumerator = enumerable.GetEnumerator();
          if(!enumerator.MoveNext())
            yield break;
      
          while (true)
          {
            yield return enumerator.Current;
            if(!enumerator.MoveNext())
              enumerator = enumerable.GetEnumerator();
          }
        }
      

      所以你可以像这样使用它

        var agents = new List<int> {1, 2, 3, 4, 123, 234, 345, 546};
      
        foreach(var i in agents.AsCircularEnumerable())
        {
          Console.WriteLine(i);
        }
      

      这将继续进行...... :)

      【讨论】:

      • 如果列表中有 3 个元素,并且如果我使用 4 或 5 的索引值 - 获取列表中的项目 - 我会得到列表的第一个和第二个元素吗?
      • 我不确定你的意思。如果您询问使用我上面概述的解决方案进行索引,因为这不是一个列表,它是一个 IEnumerable,并且您不能在 IEnumerable 上使用索引器,那么不,您不会。您可以改用agents.AsCircularEnumerable().Skip(10).First() 之类的东西。
      【解决方案4】:

      我喜欢Vinicius's idea 使用扩展方法。不幸的是,他发布的代码会引发异常。这是基于他的,但它不会抛出异常并且非常简单易读(恕我直言):

      public static T Next<T>(this IList<T> list, T item)
      {
          var nextIndex = list.IndexOf(item) + 1;
      
          if (nextIndex == list.Count)
          {
              return list[0];
          }
      
          return list[nextIndex];
      }
      

      如果传入的项不在列表中,它将返回列表中的第一项,因为list.IndexOf(item)在这种情况下将返回-1

      【讨论】:

      • Koveras,哪里会引发异常?
      • 记住 list.IndexOf(item) 将返回 -1 如果没有找到项目。
      • 这对于扩展来说确实是个好主意。我对其进行了一些修改并实现了它:)
      【解决方案5】:

      差别不大,但至少少了一些代码(至少在编辑器中);o)

      List<int> agents = taskdal.GetOfficeAgents(Branches.aarhusBranch);
      if (lastAgentIDAarhus != -1)
      {
          int index = agents.IndexOf(lastAgentIDAarhus);
          lastAgentIDAarhus = (agents.Count > index + 1 ? agents[index + 1] : agents[0]); 
      }
      else
      {
          lastAgentIDAarhus = agents[0];
      }
      

      【讨论】:

        【解决方案6】:

        如果我们添加一些检查来避免常见错误,您怎么看?

        public static class ListExtensions
        {
            public static TType Next<TType>(this IList<TType> list, TType item)
            {
                if (list == null) return default(TType);
        
                var itemIndex = list.IndexOf(item);
                if (itemIndex < 0) return list.FirstOrDefault();
        
                var nextIndex = itemIndex + 1;
        
                return nextIndex >= list.Count 
                    ? list.FirstOrDefault() 
                    : list[nextIndex];
            }
        }
        

        【讨论】:

          【解决方案7】:

          字符串 line = lines[lines.FindIndex(x => x.Contains(item)) + 1];

          【讨论】:

            猜你喜欢
            • 2012-02-11
            • 2011-02-11
            • 1970-01-01
            • 1970-01-01
            • 2022-08-17
            • 2018-02-22
            • 2018-02-18
            • 1970-01-01
            • 2011-01-11
            相关资源
            最近更新 更多