2
votes

Récupère n (partie de) objets à partir d'une liste d'objets, à partir de n index

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 ();


0 commentaires

5 Réponses :


0
votes

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 ;


0 commentaires

0
votes

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();
}


0 commentaires

1
votes

Skip + Take devrait fonctionner correctement, essayez ceci:

int firstIndex = selectedIndex - itemsToTake / 2;
firstIndex = firstIndex < 0 ? 0 : firstIndex;
return list.Skip(firstIndex).Take(itemsToTake);


0 commentaires

0
votes
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;
  }
}

0 commentaires

1
votes

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


0 commentaires