web-dev-qa-db-fra.com

Sélectionner plusieurs champs de la liste dans Linq

En ASP.NET C #, j'ai une structure:

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 sélectionner category_id et category_name, en exécutant une DISTINCT et enfin une 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 ne donne que le nom de la catégorie. Ma question est la suivante: comment obtenir plusieurs champs et dans quelle structure de données vais-je stocker cela (pas un string[])?

MODIFIER

L'utilisation d'une liste de structures n'est pas figée. S'il serait souhaitable de modifier la structure de mes données de sauvegarde pour faciliter la sélection (j'en rédigerai beaucoup), je prendrai volontiers des recommandations.

112
Chet

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();
200
Jason
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!

23
IRBMe

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 renverra 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.

22
Mehrdad Afshari

C’est une tâche pour laquelle 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();
5
Noldorin
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.

4
Paul van Brenk

Vous pouvez en faire un KeyValuePair, ainsi il retournera un "IEnumerable<KeyValuePair<string, string>>"

Donc, ce sera comme ça:

.Select(i => new KeyValuePair<string, string>(i.category_id, i.category_name )).Distinct();
3
Victor
(from i in list
 select new { i.category_id, i.category_name })
 .Distinct()
 .OrderBy(i => i.category_name);
3
Joe Chung

Vous pouvez sélectionner plusieurs champs à l'aide de linq Select, comme indiqué ci-dessus dans divers exemples, qui sera retourné sous forme de type anonyme. Si vous voulez éviter ce type anonyme, voici une astuce simple.

var items = listObject.Select(f => new List<int>() { f.Item1, f.Item2 }).SelectMany(item => item).Distinct();

Je pense que cela résout votre problème

2
AR M
public class Student
{
    public string Name { set; get; }
    public int ID { set; get; }
}

class Program
{
  static void Main(string[] args)
    {
        Student[] students =
        {
        new Student { Name="zoyeb" , ID=1},
        new Student { Name="Siddiq" , ID=2},
        new Student { Name="sam" , ID=3},
        new Student { Name="james" , ID=4},
        new Student { Name="sonia" , ID=5}
        };

        var studentCollection = from s in students select new { s.ID , s.Name};

        foreach (var student in studentCollection)
        {
            Console.WriteLine(student.Name);
            Console.WriteLine(student.ID);
        }
    }
}
0
Zoyeb Shaikh