2010-09-28 8 views
1

J'ai essentiellement une table avec des en-têtes que je lis depuis une base de données en utilisant linq en C#. Parmi ces en-têtes, il y en a toujours au moins une qui est toujours la même; Total et je veux que ça soit toujours sur la droite.Linq OrderBy Valeur d'attribut et groupe

Voici donc comment mon genre de données sont disposées:

Data 
{ 
    Label, 
    Value, 
    Age //Not used initially 
} 

données Exemple:

{"Dog", 7} 
{"Cat", 3} 
{"Other", 4} 
{"Total", 14} 

Je voudrais commander les étiquettes dans cet ordre; les noms d'animaux réels sont classés par leur valeur dans l'ordre décroissant et Total est ajouté à la fin:

"Dog", "Other", "Cat", "Total" 

Comment puis-je faire dans LINQ. Comment puis-je commander un attribut basé sur la valeur d'un autre attribut?

Une fois que j'ai l'ordre des en-têtes, existe-t-il un moyen facile de commander les rangées futures en fonction de l'ordre déjà déterminé. Si je veux d'abord trouver des en-têtes où (x => x.Age> 20) comment puis-je trier les étiquettes dans où (x => x.Age < = 20) basé sur le même ordre que l'ensemble> 20?

+0

pourquoi entreposez-vous au total? Ne peut-il pas être calculé et ajouté juste à la fin de votre liste? Ensuite, vous pouvez simplement trier par âge décroissant. Ou est-ce que je manque quelque chose? – jim

+0

C'est simplifié. Total n'est pas le nom d'attribut réel. Et il ne peut pas toujours être calculé en additionnant. – Harry

Répondre

4

Cette requête devrait fonctionner:

var query = from row in table 
      let ignore = row.Label == "Total" 
      orderby ignore, row.Value descending 
      select row.Label; 

//and corresponding lambda version 
var lquery = table.OrderBy(row => row.Label == "Total") 
        .ThenByDescending(row => row.Value) 
        .Select(row => row.Label); 

Note: il est pas tout à fait nécessaire de créer une variable ignore, il pourrait être placé directement dans la clause orderby. De cette façon, cela le rend plus lisible.

Vous ne savez pas exactement ce que vous demandez dans votre deuxième question.


modifier:
En réponse à votre commentaire, il dépendra de la façon dont vous voulez que le tri au travail, au moins écrit comme celui-ci. Cela fonctionne bien s'il n'y a qu'une seule ligne dans la table que vous voulez complètement ignorer. Pas tellement si vous en aviez plus d'un. Le problème étant que parmi les lignes "ignorées", sera également trié par le tri original (dans ce cas, par Value). Une manière naïve d'ajouter une autre ligne consiste à ajouter à la condition d'ignorance.

var query = from row in table 
      let ignore = row.Label == "Total" || row.Label == "Cost" 
      orderby ignore, row.Value descending 
      select row.Label; 

Pour avoir un ordre spécifique parmi les « lignes » ignorés, il faudrait une requête un peu plus complexe:

var query = from row in table 
      let ignore = row.Label == "Total" || row.Label == "Cost" 
      let ignoreorder = row.Label == "Cost" ? 1 : 0 
      orderby ignore, ignoreorder, row.Value descending 
      select row.Label; 

//and corresponding lambda version 
var lquery = table.OrderBy(row => row.Label == "Total" || row.Label == "Cost") 
        .ThenBy(row => row.Label == "Cost" ? 1 : 0) 
        .ThenByDescending(row => row.Value) 
        .Select(row => row.Label); 
+0

A quoi ressemblerait la syntaxe si j'avais plus d'une colonne "ignore". Comme Total et Coût. Et j'ai toujours voulu que Cost soit après ignorer. De plus, à quoi ressemblerait la syntaxe de l'expression lambda? Cela a résolu ma première question. Merci. Je vais travailler sur la seconde et peut-être clarifier davantage dans une autre question. – Harry