Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

288
Visualizações
How to iterate a collection between two items?

Consider for example a List of objects:

List<MyClass> myList;

I have a method which passes two references to items within the list. I want to iterate all items within the given ones (note: I don't know which of the two items comes first within the list):

privat void MyFunction(MyClass listItem, MyClass anotherListItem)
{
    foreach(var item in ????)
    {
        // do something 
    }
}

Currently I have solved this usecase as follows:

int listItemIdx = myList.IndexOf(listItem);
int anotherListItemIdx = myList.IndexOf(anotherListItem);

if(listItemIdx < anotherListItemIdx )
{
    for(int i = listItemIdx ; i <= anotherListItemIdx ; i++)
    {
        // do stuff
    }
}
else
{
    for (int i = anotherListItemIdx ; i < listItemIdx ; i++)
    {
        // do stuff
    }
}

I was wondering if there is a more elegant, efficient or built-in solution to this problem?

over 4 years ago · Santiago Trujillo
5 Respostas
Responde à pergunta

0

Is the list sorted? The you can use that fact to realize which item must be first. Nevertheless you can do with one for-loop, if you prefer:

private static void MyFunction(string item1, string item2)
{
    List<string> input = new() {"A", "B", "C", "D", "E"};

    int index1 = input.IndexOf(item1);
    int index2 = input.IndexOf(item2);
    int beginIndex = Math.Min(index1, index2);
    int count = Math.Abs(index1 - index2) + 1;

    foreach (string item in input.GetRange(beginIndex, count))
    {
        Console.Write(item);
    }
}
over 4 years ago · Santiago Trujillo Relatório

0

You iterate three times over the list: Two times in IndexOf, and then once again in your loop. You can make your code more efficient with this code, which iterates only once over the list.

privat void MyFunction(MyClass listItem, MyClass anotherListItem)
{
    bool betweenTwoItems = false;
    foreach(var item in myList)
    {
        if(item == listItem || item == anotherListItem)
        {
            betweenTwoItems = !betweenTwoItems;
            if(!betweenTwoItems)
            {
               break;
            }
        }

        if(betweenTwoItems )
        {
            // do stuff
        }
    }
}

We set a bool variable if we are between the two items. In the beginning, it is false. The we iterate over the list and check whether the current item is one of the two method parameters. If this is the case, we invert the value of the bool. If after the inversion of the bool the value is false, we can leave the list. After that, we check whether the bool is true. If so, we can do stuff.

Online demo: https://dotnetfiddle.net/xYcr7V

over 4 years ago · Santiago Trujillo Relatório

0

If you are looking for performance (IndexOf twice can be a bit slow) and generalization (when myList is not necessary List<T> but IEnumerable<T> only) you can put it as

bool proceed = false;
MyClass lastItem = default; 

foreach (var item in myList) {
  if (!proceed) {
    if (proceed = item == listItem) 
      lastItem = anotherListItem; 
    else if (proceed = item == anotherListItem) 
      lastItem = listItem; 
  }

  if (proceed) {
    //TODO: do staff here

    if (item == lastItem)
      break; 
  } 
}
over 4 years ago · Santiago Trujillo Relatório

0

Your existing solution can be improved:

int listItemIdx = myList.IndexOf(listItem);
int anotherListItemIdx = myList.IndexOf(anotherListItem);
int startIdx = Math.Min(listItemIdx, anotherListItemIdx);
int endIdx = Math.Max(listItemIdx, anotherListItemIdx);

for(int i = startIdx ; i <= endIdx ; i++)
{
    // do stuff
}

Thus, the code duplication disappears and only a minor refactoring is required.

To create a range-loop version, you can create a subset using GetRange(), something like:

int listItemIdx = myList.IndexOf(listItem);
int anotherListItemIdx = myList.IndexOf(anotherListItem);
int startIdx = Math.Min(listItemIdx, anotherListItemIdx);
int endIdx = Math.Max(listItemIdx, anotherListItemIdx);
var subset = myList.GetRange(startIdx, endIdx - startIdx);

foreach(var item in subset)
{
    // do stuff
}

Thus, filtering the list and processing the list can now be separated.

over 4 years ago · Santiago Trujillo Relatório

0

More generic version of the same idea. So this can be created as extension method for IEnumerable<,>

public static IEnumerable<T> RangeOf<T>(this IEnumerable<T> elements, T el1, T el2, 
  IEqualityComparer<T> comparer = null)
{
  comparer ??= EqualityComparer<T>.Default;
  var hasStarted = false;
  var end = default;
        
  foreach (T el in elements)
  {
    if (!hasStarted) 
    {
      hasStarted = comparer.Equals(el, el1) || comparer.Equals(el, el2);
      end = comparer.Equals(el, el1) ? el2 : el1;
    }
            
    if (hasStarted)
      yield return el;
            
    if (comparer.Equals(el, end))
      yield break;
  }
}

and version with the while loop supporting ranges from el to el. For example for [5, 0, 1, 2, 0, 6] the range [0, 0] will be [0, 1, 2, 0]:

public static IEnumerable<T> RangeOf<T>(this IEnumerable<T> elements, T el1, T el2,
  IEqualityComparer<T> comparer = null)
{   
  comparer ??= EqualityComparer<T>.Default;
  var hasStarted = false;
  var end = default;
        
  var it = elements.GetEnumerator();
  while (!hasStarted && it.MoveNext())
  {
    T el = it.Current;
    hasStarted = comparer.Equals(el , el1) || comparer.Equals(el , el2);
    end = comparer.Equals(it.Current, el1) ? el2 : el1;
  }
        
  if (hasStarted)
    yield return it.Current;
        
  while (it.MoveNext())
  {
    yield return it.Current;

    if (comparer.Equals(it.Current, end))
      yield break;
  }
}

both can be used like this

foreach (var el in list.RangeOf(listItem, anotherListItem))
  // Do with el whatever you want to do
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda