Выберите несколько полей из списка в Linq

В ASP.NET С# у меня есть структура:

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

и у меня есть Список этих. Я хочу выбрать category_id и category_name, запустив DISTINCT и, наконец, ORDERBY на category_name.

Вот что у меня сейчас:

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

Это, очевидно, просто получает название категории. Мой вопрос: как мне получить несколько полей и какую структуру данных я буду хранить в этом (а не string[])?

ИЗМЕНИТЬ

Использование списка структур не задано в камне. Если было бы целесообразно изменить мою структуру данных резервного копирования, чтобы облегчить выбор (я буду писать много из них), тогда я бы с радостью принял рекомендации.

Ответ 1

Анонимные типы позволяют вам выбирать произвольные поля в структуры данных, которые в дальнейшем будут введены в ваш код:

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

Поскольку вам (по-видимому) необходимо сохранить его для последующего использования, вы можете использовать оператор GroupBy:

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

Ответ 2

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);

Изменить: сделал больше LINQ-ey!

Ответ 3

Вы можете использовать анонимный тип:

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

Компилятор будет генерировать код для класса с name и category_name свойствами и возвращает экземпляры этого класса. Вы также можете вручную указать имена свойств:

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

У вас может быть произвольное количество свойств.

Ответ 4

Это задача, для которой анонимные типы очень хорошо подходят. Вы можете возвращать объекты типа, созданного автоматически компилятором, исходя из использования.

Синтаксис такой формы:

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

В вашем случае попробуйте следующее:

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

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

Это использует анонимные типы, поэтому вам нужно ключевое слово var, так как результирующий тип выражения неизвестен заранее.

Ответ 6

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

Ответ 7

Вы можете выбрать несколько полей, используя linq. Выберите, как показано выше, в разных примерах, это будет отображаться как анонимный тип. Если вы хотите избежать этого анонимного типа, это простой трюк.

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

Я думаю, что это решает вашу проблему

Ответ 8

Вы можете сделать это KeyValuePair, поэтому он вернет "IEnumerable<KeyValuePair<string, string>>"

Итак, это будет так:

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