从Linq中的列表中选择多个字段

时间:2009-07-29 20:55:22

标签: c# linq data-structures

在ASP.NET C#中我有一个结构:

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

我有一份清单。我想选择category_idcategory_name,在DISTINCT上运行ORDERBY,最后选择category_name

这就是我现在所拥有的:

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

这显然只是得到了类别名称。我的问题是,我如何获得多个字段,以及将其存储在哪个数据结构中(不是string[])?

修改

使用结构列表并非一成不变。如果建议更改我的支持数据结构以使选择更容易(我将写很多这些),那么我很乐意接受建议。

10 个答案:

答案 0 :(得分:208)

匿名类型允许您在以后在代码中强类型化的数据结构中选择任意字段:

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

答案 1 :(得分:23)

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!

答案 2 :(得分:22)

您可以使用匿名类型:

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

编译器将为具有namecategory_name属性的类生成代码,并返回该类的实例。您也可以手动指定属性名称:

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

您可以拥有任意数量的属性。

答案 3 :(得分:5)

这是anonymous types非常适合的任务。您可以返回由编译器自动创建的类型的对象,从使用情况推断。

语法是这种形式:

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

答案 4 :(得分:4)

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

这使用匿名类型,因此您必须使用var关键字,因为事先不知道表达式的结果类型。

答案 5 :(得分:4)

您可以将其设为KeyValuePair,因此会返回"IEnumerable<KeyValuePair<string, string>>"

所以,它会是这样的:

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

答案 6 :(得分:3)

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

答案 7 :(得分:2)

您可以使用linq选择多个字段选择如上所示,在各种示例中,它将作为匿名类型返回。如果你想避免这种匿名类型,这是一个简单的技巧。

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

我认为这解决了你的问题

答案 8 :(得分:0)

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

答案 9 :(得分:0)

根据电子邮件地址的共享密钥给出List<MyType1> internalUsersList<MyType2> externalUsers ...


对于C#7.0 +:

var matches = (
    from i in internalUsers
    join e in externalUsers
    on i.EmailAddress.ToUpperInvariant() equals e.Email.ToUpperInvariant()
    select (internalUser:i, externalUser:e)
).ToList();

哪个给您matches作为List<(MyType1, MyType2)>

如果需要,您可以在此处进行比较:

var internal_in_external = matches.Select(m => m.internalUser).ToList();
var external_in_internal = matches.Select(m => m.externalUser).ToList();

var internal_notIn_external = internalUsers.Except(internal_in_external).ToList();
var external_notIn_internal = externalUsers.Except(external_in_internal).ToList();

internal_in_externalinternal_notIn_external的类型为List<MyType1>

external_in_internalexternal_notIn_internal的类型为List<MyType2>


对于7.0之前的C#版本:

var matches = (
    from i in internalUsers
    join e in externalUsers
    on i.EmailAddress.ToUpperInvariant() equals e.Email.ToUpperInvariant()
    select new Tuple<MyType1, MyType2>(i, e)
).ToList();

哪个给您matches作为List<Tuple<MyType1, MyType2>>

如果需要,您可以在此处进行比较:

var internal_in_external = matches.Select(m => m.Item1).ToList();
var external_in_internal = matches.Select(m => m.Item2).ToList();

var internal_notIn_external = internalUsers.Except(internal_in_external).ToList();
var external_notIn_internal = externalUsers.Except(external_in_internal).ToList();

internal_in_externalinternal_notIn_external的类型为List<MyType1>

external_in_internalexternal_notIn_internal的类型为List<MyType2>