J'ai une liste de n objets. Je veux saisir un maximum de n éléments (-n éléments précédents et n + éléments suivants), à partir de l'index sélectionné. Je veux une méthode pour cela, dans laquelle je fournis la liste avec certains paramètres.
Comment puis-je y parvenir en C #?
Premier exemple:
int selectedIndex = 5
int itemsToTake = 4 (2 précédents et 2 suivants)
Liste renvoyée = 3-4-5-6-7
Deuxième exemple:
int selectedIndex = 1
int itemsToTake = 4 (prend 1 précédent et 3 suivant, car la liste commence par 0)
Returned list = 0-1-2-3-4
J'ai déjà essayé une combinaison de list.skip (). Take (), mais cela ne s'est pas très bien passé. p>
Exemple:
nextIndex = nextIndex - prevIndex + 1; return List.Skip (prevIndex) .Take (nextIndex) .ToList ();
5 Réponses :
Tout d'abord, assurez-vous que la liste contient suffisamment d'éléments:
return List.Skip(firstIndex).Take(itemsToTake + 1).ToList();
Le premier index que vous voulez prendre est (sans tenir compte des bordures de séquence):
if(firstIndex < 0) firstIndex = 0; if(firstIndex + nitemsToTake >= List.Count) firstIndex = List.Count - 1 - itemsToTake ;
Vous devez gérer le cas particulier où selectedIndex - itemsToTake / 2
est inférieur à 0:
public static List<T> Take<T>(this List<T> list, int selectedIndex, int itemsToTake) { if (selectedIndex - n / 2 < 0) { return list.Take(itemsToTake + 1).ToList(); } return list.Skip(selectedIndex - itemsToTake / 2).Take(itemsToTake +1).ToList(); }
Skip + Take devrait fonctionner correctement, essayez ceci:
int firstIndex = selectedIndex - itemsToTake / 2; firstIndex = firstIndex < 0 ? 0 : firstIndex; return list.Skip(firstIndex).Take(itemsToTake);
public static IEnumerable<T> Nearby<T>(IEnumerable<T> source, int selectedIndex, int itemsToTake) { itemsToTake = ((itemsToTake/2)*2)+1; Queue<T> queue = new Queue<T>(); bool foundItem = false; int afterItemCount = 0; int recommendedAfterItemCount = itemsToTake/2; foreach(var pair in source.Select((t, i) => new {t, i})) { T t = pair.t; int i = pair.i; queue.Enqueue(t); if (itemsToTake < queue.Count) queue.Dequeue(); if (i == selectedIndex) foundItem = true; else if (foundItem) afterItemCount += 1; bool enoughItems = queue.Count == itemsToTake; bool enoughAfterItems = recommendedAfterItemCount <= afterItemCount; if (enoughItems && enoughAfterItems) break; } foreach(T t in queue) { yield return t; } }
Une manière inefficace mais visuellement esthétique de le faire:
var source = Enumerable.Range(0, 10); Console.WriteLine($"Result: {String.Join(", ", source.Nearby(5, 5))}");
Exemple d'utilisation:
public static IEnumerable<T> Nearby<T>(this IEnumerable<T> source, int selectedIndex, int itemsToTake) { var left = source.Take(selectedIndex).Reverse().Take(itemsToTake / 2).Reverse(); var middle = source.ElementAt(selectedIndex); var right = source.Skip(selectedIndex).Skip(1).Take(itemsToTake / 2); return left.Append(middle).Concat(right); }
Résultat:
Résultat: 3, 4, 5, 6, 7