Список <> Получить следующий элемент или получить первый

Я хочу получить следующий элемент в списке, и если список у него заканчивается, я хочу первый элемент. Поэтому я просто хочу, чтобы это было кругом, другими словами.

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

Я довольно недоволен своим собственным решением, показанным выше, дайте мне знать, если у вас есть лучший вариант:)

Ответ 1

lastAgentIDAarhus = agents[index == -1 ? 0 : index % agents.Count];

Использование оператора MOD % atuomatically отбивает индекс до диапазона возможных индексов.

Оператор modulo является комплиментом оператору DIV (/) и возвращает остаток от деления двух целых чисел. Например, если вы разделите 9 на 6, результат будет равен 1 с остатком 3. Оператор MOD запросит 3.

Ответ 2

Или просто:

public static T NextOf<T>(this IList<T> list, T item)
{
     return list[(list.IndexOf(item) + 1) == list.Count ? 0 : (list.IndexOf(item) + 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);
  }

Что будет продолжаться...:)

Ответ 4

Мне нравится идея Vinicius использования метода расширения. К сожалению, он отправил исключение. Это основано на его, но оно не будет генерировать исключение, и это очень просто и легко читать (IMHO):

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 в этом случае;

Ответ 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

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