web-dev-qa-db-fra.com

Linq Query Group by et sélection des premiers éléments

J'ai un tableau de chaînes un peu comme ceci:

// icon, category, tool
String[,] subButtonData = new String[,]
{
    {"graphics/gui/brushsizeplus_icon", "Draw", "DrawBrushPlus"},
    {"graphics/gui/brushsizeminus_icon", "Draw", "DrawBrushMinus"},
    {"graphics/gui/freedraw_icon", "Draw", "DrawFree"},
    {"graphics/gui/linedraw_icon", "Draw", "DrawLine"},
    {"graphics/gui/rectangledraw_icon", "Draw", "DrawRectangle"},
    {"graphics/gui/ellipsedraw_icon", "Draw", "DrawEllipse"},
    {"graphics/gui/brushsizeplus_icon", "Brusher", "BrusherBrushPlus"},
    {"graphics/gui/brushsizeminus_icon", "Brusher", "BrusherBrushMinus"},
    {"graphics/gui/brushsizeplus_icon", "Text", "TextBrushPlus"},
    {"graphics/gui/brushsizeminus_icon", "Text", "TextBrushMinus"},
};

Ensuite, je remplis un List<Button> avec mon type de bouton nommé mainButtons

Voici comment je demande un regroupement pour Category:

var categories = from b in mainButtons
                 group b by b.category into g
                 select new { Category = g.Key, Buttons = g };

Comment puis-je sélectionner le premier élément de chaque groupe dans ma liste principale? (sans itérer chacun et ajouter à une autre liste?)

55
JML

Voir LINQ: comment obtenir le dernier/dernier enregistrement avec une clause group by

var firstItemsInGroup = from b in mainButtons
                 group b by b.category into g
select g.First();

Je suppose que les boutons principaux sont déjà triés correctement.

Si vous devez spécifier un ordre de tri personnalisé, utilisez la substitution OrderBy avec Comparer.

var firstsByCompareInGroups = from p in rows
        group p by p.ID into grp
        select grp.OrderBy(a => a, new CompareRows()).First();

Voir un exemple dans mon article "Sélectionner la première ligne du groupe à l'aide de Comparer personnalisé "

61
Michael Freidgeim
var result = list.GroupBy(x => x.Category).Select(x => x.First())
68
Oscar Fraxedas
var results = list.GroupBy(x => x.Category)
            .Select(g => g.OrderBy(x => x.SortByProp).FirstOrDefault());

Pour ceux qui se demandent comment faire cela pour les groupes qui ne sont pas nécessairement triés correctement, voici une extension de cette réponse qui utilise la méthode syntaxe pour personnaliser l'ordre de tri de chaque groupe et ainsi obtenir l'enregistrement souhaité de chacun.

Remarque: Si vous utilisez LINQ-to-Entities, vous obtiendrez une exception d'exécution si vous utilisez First () au lieu de FirstOrDefault () ici car la première ne peut être utilisée que comme opération de requête finale.

11
ihake

Tout d'abord, je n'utiliserais pas de tableau multidimensionnel. Je n'ai vu que de mauvaises choses en sortir.

Configurez votre variable comme ceci:

IEnumerable<IEnumerable<string>> data = new[] {
    new[]{"...", "...", "..."},
    ... etc ...
};

Ensuite, vous iriez simplement:

var firsts = data.Select(x => x.FirstOrDefault()).Where(x => x != null); 

Le Where s'assure qu'il élague toutes les valeurs nulles si vous avez une liste vide comme élément à l'intérieur.

Vous pouvez également l'implémenter comme:

string[][] = new[] {
    new[]{"...","...","..."},
    new[]{"...","...","..."},
    ... etc ...
};

Cela pourrait être utilisé de manière similaire à un [x,y] tableau mais il est utilisé comme ceci: [x][y]

5
Aren