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