2009-07-29 17 views
101

w ASP.NET C# Mam struct:wybrać kilka pól z listy w Linq

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

i mam listę tych. Chcę wybrać category_id i category_name, uruchamiając DISTINCT i ostatecznie ORDERBY na category_name.

Oto co mam teraz:

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

To oczywiście tylko dostaje nazwę kategorii. Moje pytanie brzmi: w jaki sposób mogę uzyskać wiele pól i jaką strukturę danych przechowuję (nie string[])?

EDIT

Korzystanie listę elemencie nie jest ustawione w kamieniu. Jeśli byłoby wskazane, aby zmienić strukturę moich danych, aby ułatwić wybór (wiele z nich piszę), to chętnie przyjmę zalecenia.

+8

Chociaż to niezwiązane ze stroną LINQ, zdecydowanie * nie zalecałbym używania zmiennych struktur lub pól publicznych. Osobiście rzadko tworzyłem struktury, ale zmienne struktury tylko proszą o kłopoty. –

+0

@Jon Skeet Dzięki. Zamienię go na regularną klasę z członkami prywatnymi. – Chet

+1

@Jon Skeet Dlaczego? – Midhat

Odpowiedz

175

anonimowych typy pozwalają na wybór dowolnych pól do struktur danych, które są silnie wpisane później w swoim kodzie:

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

Od Ciebie (widocznie) trzeba go przechowywać r późniejszego wykorzystania, można użyć operatora GroupBy:

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

Chcę używać różnych na 1 kolumnie i pobrać wiele kolumn.SO jak mogę to zrobić? –

+1

Nigdy nie myślałem, że "Wybierz" do nowego typu. W moim przypadku wybrałem nową "KeyValuePair". – cjbarth

20

Można użyć typ anonimowy:

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

Kompilator generuje kod dla klasy z name i category_name właściwości i zwraca instancji tej klasy. Można również ręcznie określić nazwy właściwości:

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

Możesz mieć dowolną liczbę właściwości.

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

Używa anonimowych typów, więc musisz użyć słowa kluczowego var, ponieważ wynikowy typ wyrażenia nie jest z góry znany.

5

Jest to zadanie, do którego bardzo dobrze pasuje anonymous types. Możesz zwrócić obiekty typu, który jest tworzony automatycznie przez kompilator, wywnioskowane z użycia.

Składnia jest z tego formularza:

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

Twoim przypadku, spróbuj coś jak następuje:

var listObject = getData(); 
var catNames = listObject.Select(i => 
    new { CatName = i.category_name, Item1 = i.item1, Item2 = i.item2 }) 
    .Distinct().OrderByDescending(s => s).ToArray(); 
22
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: staje się on bardziej LINQ-ey!

+0

Haha, dzięki, cóż, doceniam pomoc. Najwyraźniej nie było to najtrudniejsze pytanie na świecie. – Chet

+0

@IRBMe Przepraszam, małe pytanie. Czym dokładnie jest "wartość"? –

3
(from i in list 
select new { i.category_id, i.category_name }) 
.Distinct() 
.OrderBy(i => i.category_name); 
2

Możesz wybrać wiele pól za pomocą linq Wybierz, jak pokazano powyżej w różnych przykładach, które powrócą jako typ anonimowy. Jeśli chcesz uniknąć tego anonimowego typu, oto prosta sztuczka.

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

myślę, że to rozwiąże problem

2

Można dokonać jej KeyValuePair, więc będzie zwracać "IEnumerable<KeyValuePair<string, string>>"

Tak, to będzie tak:

.Select(i => new KeyValuePair<string, string>(i.category_id, i.category_name)).Distinct();