2010-03-08 5 views
9

Étant donné une liste d'éléments comme ceci:LINQ pour sélectionner une gamme de membres dans une liste

int[] ia = new int[] { -4, 10, 11, 12, 13, -1, 9, 8, 7, 6, 5, 4, -2, 
         6, 15, 32, -5, 6, 19, 22 }; 

est-il un moyen facile à Linq de faire quelque chose le long des lignes de « Sélectionnez les éléments de la - 1 jusqu'au nombre négatif suivant (ou la liste s'épuise) "? Un résultat réussi pour -1 serait (-1, 9, 8, 7, 6, 5, 4). L'utilisation de -2 donnerait le résultat (-2, 6, 15, 32).

Pas un problème de devoirs. Je regarde juste une implémentation utilisant une bool, une boucle for, et une if se demandant s'il y a une manière plus propre de le faire.

Répondre

11

Jetez un oeil à la méthode d'extension TakeWhile Linq. Prend des éléments de la liste tant que la condition est vraie, ignore le reste.

Exemple:

int[] ia = new int[] { -4, 10, 11, 12, 13, -1, 9, 8, 7, 6, 5, 4, -2, 
         6, 15, 32, -5, 6, 19, 22 }; 

var result = ia 
      .SkipWhile(i => i != -1) 
      .Skip(1) 
      .TakeWhile(i => i >= 0); 

Notez le saut (1) après la SkipWhile. SkipWhile ignore tout, mais n'inclut pas l'élément correspondant. TakeWhile Prend alors les éléments, jusqu'à mais n'incluant pas l'élément correspondant. Parce que -1 n'est pas supérieur ou égal à zéro, vous obtenez un résultat vide.

+0

J'ai essayé 'SkipWhile' /' TakeWhile' et a fait la même erreur que Anders. Il ne m'est pas venu à l'esprit d'ignorer celui-là. Je vais laisser cela ouvert un peu plus longtemps pour voir quelle variété tombe. –

+0

Cette solution n'inclura pas le premier '-1' dans le jeu de résultats. –

+0

Ce n'est pas vrai. Mais puisque le -1 était l'indicateur pour le début de l'ensemble - c'est celui, valeur connue - il peut être inséré dans les résultats. –

5

Mise à jour

Cette fois, je l'ai testé le code ... En utilisant les deux sous forme de paramètre de TakeWhile nous pouvons le forcer à accepter le premier élément (j == 0) même lorsque le test i n'est pas satisfait .

ia.SkipWhile(i => i != -1).TakeWhile((i, j) => i >= 0 || j == 0)

TakeWhile(Func<int, int, bool>) nécessite une fonction/lambda qui prend deux paramètres. La première étant la valeur à tester, la seconde étant l'indice de l'élément.

+0

Pensée de cela et cela donne un résultat vide. –

+0

Vous avez raison de dire que TakeWhile (i => i> = 0) donne un résultat vide. Voir mon effort mis à jour (et testé) ci-dessus. –

+0

Cela donne les bons résultats maintenant. –

0

Est-ce que ça doit être Linq? Vous pouvez utiliser les méthodes Extensions pour obtenir une solution plus propre.

int[] ia = new int[] { -4, 10, 11, 12, 13, -1, 9, 8, 7, 6, 5, 4, -2, 
         6, 15, 32, -5, 6, 19, 22 }; 

// Call the Extension method 
int[] results = ia.SelectRangeLoop(-2); 

// Print Results 
for (int i = 0; i < results.Length; i++) 
{ 
    Console.Write(" {0} ", results[i]); 
} 

La méthode pour SelectRangeLoop est ci-dessous.

public static int[] SelectRangeLoop(this int[] value, int startNumber) 
{ 
    List<int> results = new List<int>(); 

    bool inNegative = false; 

    for (int i = 0; i < value.Length; i++) 
    { 
     if (value[i] == startNumber) 
     { 
      inNegative = true; 

      results.Add(value[i]); 

      continue; 
     } 

     if (inNegative && value[i] < 0) 
     { 
      break; 
     } 

     if (inNegative) 
     { 
      results.Add(value[i]); 
     } 
    } 

    return results.ToArray(); 
} 
+0

Ne doit pas être Linq mais il semblait un choix évident .. Vous avez simplement déplacé le 'for',' if', et 'bool' ailleurs. Si je le faisais souvent et que je n'avais pas d'option plus concise, cela pourrait être une méthode de vulgarisation utile. –

0
var first = ia.Select((i, index) => new {i, index}).Where((i, index) => i.i == x).First(); 
var ind = first.index; 
var second = ia.SkipWhile((i, index) => index <= ind).TakeWhile(i => i > 0); 
var ints = new[]{first.i}.Union(second); 
+0

{7, -1, 4, -1, 5} donne {-1, 4, -1, 5} au lieu de {-1, 4} avec cette solution. –

Questions connexes