146 votes

Sélectionner plusieurs champs de la liste dans Linq

Dans ASP.NET C# j'ai une structure (struct):

public struct Data
{
    public int item1;
    public int item2;
    public int category_id;
    public string category_name;
}

et j'ai une Liste de ceux-ci. Je veux choisir category_id et category_name, l'exécution d'un DISTINCT et enfin un ORDERBY sur category_name.

Voici ce que j'ai maintenant:

List<Data> listObject = getData();
string[] catNames = listObject
                    .Select(i=> i.category_name)
                    .Distinct()
                    .OrderByDescending(s => s)
                    .ToArray();

De toute évidence, cela se fait tout simplement le nom de la catégorie. Ma question est, comment puis-je obtenir plusieurs champs, et quelle structure de données sera-je conserver ce (pas un string[])?

MODIFIER

À l'aide d'une liste de structures n'est pas gravé dans la pierre. Si il serait souhaitable de modifier mes données de sauvegarde de la structure à faire une sélection plus facile (je vais écrire beaucoup de ces derniers), alors je serais heureux de prendre les recommandations.

258voto

Jason Points 11332

Les types anonymes vous permettent de sélectionner des champs arbitraires dans des structures de données fortement typées ultérieurement dans votre code:

 var cats = listObject
    .Select(i => new { i.category_id, i.category_name })
    .Distinct()
    .OrderByDescending(i => i.category_name)
    .ToArray();
 

Puisque vous avez (apparemment) besoin de le stocker pour une utilisation ultérieure, vous pouvez utiliser l'opérateur GroupBy:

 Data[] cats = listObject
    .GroupBy(i => new { i.category_id, i.category_name })
    .OrderByDescending(g => g.Key.category_name)
    .Select(g => g.First())
    .ToArray();
 

27voto

IRBMe Points 2127
 var selectedCategories =
	from value in
		(from data in listObject
		orderby data.category_name descending
		select new { ID = data.category_id, Name = data.category_name })
	group value by value.Name into g
	select g.First();

foreach (var category in selectedCategories) Console.WriteLine(category);
 

Edit : fait plus LINQ-ey!

24voto

Mehrdad Afshari Points 204872

Vous pouvez utiliser un type anonyme:

 .Select(i => new { i.name, i.category_name })
 

Le compilateur générera le code d'une classe avec les propriétés name et category_name et retournera des instances de cette classe. Vous pouvez également spécifier manuellement les noms de propriété:

 i => new { Id = i.category_id, Name = i.category_name }
 

Vous pouvez avoir un nombre arbitraire de propriétés.

7voto

Noldorin Points 67794

C'est une tâche pour laquelle les types anonymes sont très bien adaptés. Vous pouvez renvoyer des objets d'un type créé automatiquement par le compilateur, déduit de l'utilisation.

La syntaxe est de cette forme:

 new { Property1 = value1, Property2 = value2, ... }
 

Dans votre cas, essayez ce qui suit:

 var listObject = getData();
var catNames = listObject.Select(i =>
    new { CatName = i.category_name, Item1 = i.item1, Item2 = i.item2 })
    .Distinct().OrderByDescending(s => s).ToArray();
 

4voto

pb. Points 4609
 var result = listObject.Select( i => new{ i.category_name, i.category_id } )
 

Ceci utilise des types anonymes, vous devez donc utiliser le mot-clé var, car le type résultant de l'expression n'est pas connu à l'avance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X