2010-10-10 10 views
2
var tmpProjection = myCollection.ToLookup(t => t.SomeBoolValue); 
var listOneFinal = tmpProjection[true]; 
var listTwo = tmpProjection[false]; 

première question, est-il possible d'assigner à LISTONE et listTwo d'une manière plus courte, je sais que je suis ici d'être pointilleux, ... juste demander .Linq, en utilisant ToLookup pour projeter des valeurs différentes variables nommées

Maintenant,

var listThree = listTwo.ToLookup(t => t.SomeOtherBoolValue); 
var listFourFinal = listThree[false]; 
var listFiveFinal = listThree[true]; 

Ainsi, dans Thise cas, j'ai juste besoin (en fin de compte) listOneFinal, listFourFinal et listFiveFinal - mais je crée ce genre de choses de température entre les deux ... est-il un moyen de réduire ce.

Je ne parle que du code, pas de la performance ou de la criticité du code.

Répondre

0

Je pense que ce que vous avez là est déjà très bien, pour être honnête.

Si vous cherchez simplement à réduire le nombre de déclarations , je doute que vous pourriez faire mieux que:

var listOneFinal = myCollection.Where(t => t.SomeBoolValue); 
var listFourFinal = myCollection.Where(t => !t.SomeBoolValue && !t.SomeOtherBoolValue); 
var listFiveFinal = myCollection.Where(t => !t.SomeBoolValue && t.SomeOtherBoolValue); 

Ou peut-être:

var predicates = new Func<MyClass,bool>[]{ t => t.SomeBoolValue, t => t.SomeOtherBoolValue}; 
var listOneFinal = myCollection.Where(predicates.First()); 
var listFourFinal = myCollection.Where(t => !predicates.Any(p => p(t))); 
var listFiveFinal = myCollection.Where(t => !predicates[0](t) && predicates[1](t)); 

(Appel ToList() sur chaque requête si désiré)

Mais vraiment, je préfère votre technique beaucoup mieux, le code que j'ai fourni n'est pas parti plus lisiblement ou efficace.

Vous voudrez peut-être envisager de stocker simplement les 2 références au lieu de chaque liste et d'intégrer chaque 'recherche finale' si nécessaire car il est bon marché d'appeler Lookup[key]. Donc, chaque fois que vous avez besoin listFourFinal, il suffit d'appeler listThree[false]. De meilleurs noms de variables aideraient, évidemment.

1

Vous pouvez le faire avec moins d'instructions, mais comme vous devez terminer l'opération avec 3 valeurs, vous avez besoin d'au moins 3 affectations. Votre code est très lisible, ne sacrifiez pas la lisibilité pour "être intelligent" et réduire à moins de déclarations. Cela étant dit, voici une version à 3 états; qui fonctionnera bien si les collections sont petites (votre propre version fonctionnera mieux avec des collections plus grandes, puisque cette version itère plusieurs fois à travers la collection):

var listOneFinal = myCollection.Where(t => t.SomeBoolValue); 
var listFourFinal = myCollection.Where(t => !t.SomeBoolValue && !t.SomeOtherBoolValue); 
var listFiveFinal = myCollection.Where(t => !t.SomeBoolValue && t.SomeOtherBoolValue); 

En fonction de votre scénario réel d'utilisation, l'est peut-être au-dessus de plus lisible .

3

bool est un peu faible pour communiquer l'intention. Int est un peu mieux et enum serait le meilleur.

Lookup<int, T> myLookup = myCollection 
.ToLookup(t => 
    t.someBoolValue ? 1 : 
    t.someOtherBoolValue ? 4 : 
    5 
); 

var listOne = myLookup[1]; 
var listFour = myLookup[4]; 
var listFive = myLookup[5]; 
+0

+1: brillant, complètement raté cette idée! – Ani

0

Si vous vous trouvez souvent dans cette situation, vous pouvez écrire une fonction pour le faire. Pour un booléen ToLookup, nous pouvons utiliser le out parameters de C# pour renvoyer plusieurs valeurs.

public static void Dichotomize<T>(this IEnumerable<T> source, 
            Func<T,bool> keySelector, 
            out IEnumerable<T> affirmative, 
            out IEnumerable<T> negative) { 
    if (source == null) throw new ArgumentNullException("source"); 
    if (keySelector == null) throw new ArgumentNullException("keySelector"); 

    var affirmativeList = new List<T>(); 
    var negativeList = new List<T>(); 
    foreach (var element in source) { 
     (keySelector(element) ? affirmativeList : negativeList).Add(element); 
    } 
    affirmative = affirmativeList.AsReadOnly(); 
    negative = negativeList.AsReadOnly(); 
} 

Maintenant, nous pouvons faire:

IEnumerable<T> listOneFinal, listTwo, listFourFinal, listFiveFinal; 
myCollection.Dichotomize(t => t.SomeBoolValue, out listOneFinal, out listTwo); 
listTwo.Dichotomize(t => t.SomeOtherBoolValue, out listFiveFinal, out listFourFinal); 
Questions connexes