Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

280
Vistas
¿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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda