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

283
Visualizações
¿Cómo iterar una colección entre dos elementos?

Considere, por ejemplo, una lista de objetos:

 List<MyClass> myList;

Tengo un método que pasa dos referencias a elementos dentro de la lista. Quiero iterar todos los elementos dentro de los dados (nota: no sé cuál de los dos elementos viene primero en la lista):

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

Actualmente he resuelto este caso de uso de la siguiente manera:

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

Me preguntaba si hay una solución más elegante, eficiente o integrada para este problema.

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

0

¿Está ordenada la lista? Puede usar ese hecho para darse cuenta de qué elemento debe ser el primero. Sin embargo, puede hacerlo con un bucle for, si lo prefiere:

 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

Itera tres veces sobre la lista: dos veces en IndexOf y luego una vez más en su bucle. Puede hacer que su código sea más eficiente con este código, que itera solo una vez en la lista.

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

Establecemos una variable bool si estamos entre los dos elementos. Al principio, es falso. Luego iteramos sobre la lista y verificamos si el elemento actual es uno de los dos parámetros del método. Si este es el caso, invertimos el valor del bool. Si tras la inversión del bool el valor es falso, podemos salir de la lista. Después de eso, verificamos si el bool es verdadero. Si es así, podemos hacer cosas.

Demostración en línea: https://dotnetfiddle.net/xYcr7V

over 4 years ago · Santiago Trujillo Relatório

0

Si está buscando rendimiento ( IndexOf dos veces puede ser un poco lento) y generalización (cuando myList no es necesario List<T> pero IEnumerable<T> solamente) puede ponerlo como

 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

Su solución existente se puede mejorar:

 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 }

Por lo tanto, la duplicación de código desaparece y solo se requiere una refactorización menor.

Para crear una versión de bucle de rango, puede crear un subconjunto usando GetRange() , algo como:

 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 }

Por lo tanto, filtrar la lista y procesar la lista ahora se pueden separar.

over 4 years ago · Santiago Trujillo Relatório

0

Versión más genérica de la misma idea. Entonces esto se puede crear como método de extensión para 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; } }

y la versión con el ciclo while admite rangos de el a el . Por ejemplo, para [5, 0, 1, 2, 0, 6] el rango [0, 0] será [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; } }

ambos se pueden usar así

 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