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.
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();
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!
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.
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();
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.
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();
(from i in list
select new { i.category_id, i.category_name })
.Distinct()
.OrderBy(i => i.category_name);
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
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);
}
}
}