c# - saber - ¿Cómo puedo obtener cada enésimo elemento de una lista<T>?
recorrer una lista string c# (9)
Creo que si proporciona una extensión linq, debería poder operar en la interfaz menos específica, por lo tanto, en IEnumerable. Por supuesto, si está buscando velocidad, especialmente para N grandes, puede proporcionar una sobrecarga para el acceso indexado. Este último elimina la necesidad de iterar sobre grandes cantidades de datos no necesarios, y será mucho más rápido que la cláusula Where. Al proporcionar ambas sobrecargas, el compilador puede seleccionar la variante más adecuada.
public static class LinqExtensions
{
public static IEnumerable<T> GetNth<T>(this IEnumerable<T> list, int n)
{
if (n < 0)
throw new ArgumentOutOfRangeException("n");
if (n > 0)
{
int c = 0;
foreach (var e in list)
{
if (c % n == 0)
yield return e;
c++;
}
}
}
public static IEnumerable<T> GetNth<T>(this IList<T> list, int n)
{
if (n < 0)
throw new ArgumentOutOfRangeException("n");
if (n > 0)
for (int c = 0; c < list.Count; c += n)
yield return list[c];
}
}
Estoy usando .NET 3.5 y me gustaría poder obtener cada * n
* ésimo elemento de una lista. No me molesta si se logra usando una expresión lambda o LINQ.
Editar
Parece que esta pregunta provocó bastante debate (lo cual es bueno, ¿no?). Lo principal que aprendí es que cuando crees que sabes todas las formas de hacer algo (incluso tan simple como esto), ¡piénsalo de nuevo!
En bucle
for(int i = 0; i < list.Count; i += n)
//Nth Item..
Imho, ninguna respuesta es correcta. Todas las soluciones comienzan desde 0. Pero quiero tener el verdadero elemento enésimo
public static IEnumerable<T> GetNth<T>(this IList<T> list, int n)
{
for (int i = n - 1; i < list.Count; i += n)
yield return list[i];
}
No estoy seguro de si es posible hacerlo con una expresión LINQ, pero sé que puede usar el método de extensión Where
para hacerlo. Por ejemplo, para obtener cada quinto elemento:
List<T> list = originalList.Where((t,i) => (i % 5) == 0).ToList();
Esto obtendrá el primer elemento y cada quinto desde allí. Si desea comenzar en el quinto elemento en lugar del primero, compare con 4 en lugar de comparar con 0.
Puede usar la sobrecarga Where, que pasa el índice junto con el elemento
var everyFourth = list.Where((x,i) => i % 4 == 0);
Sé que es "vieja escuela", pero ¿por qué no usar simplemente un ciclo for con step = n?
Suena como
IEnumerator<T> GetNth<T>(List<T> list, int n) {
for (int i=0; i<list.Count; i+=n)
yield return list[i]
}
Haría el truco. No veo la necesidad de usar Linq o expresiones lambda.
EDITAR:
Hazlo
public static class MyListExtensions {
public static IEnumerable<T> GetNth<T>(this List<T> list, int n) {
for (int i=0; i<list.Count; i+=n)
yield return list[i];
}
}
y escribes de una manera LINQish
from var element in MyList.GetNth(10) select element;
2da Edición :
Para hacerlo aún más LINQish
from var i in Range(0, ((myList.Length-1)/n)+1) select list[n*i];
return list.Where((x, i) => i % nStep == 0);