在 Linq 中从 List 中选择多个字段

在 ASP.NET C # 中,我有一个 struct:

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

我有一个清单。我想选择 category_idcategory_name,在 category_name上运行 DISTINCTORDERBY

这是我现在拥有的:

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

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

剪辑

使用结构列表不是一成不变的。如果改变我的支持数据结构使得选择更加容易(我会写很多这样的文章)是明智的,那么我很乐意接受建议。

526711 次浏览

你可以使用匿名类型:

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

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

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

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

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

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

这是 < em > 匿名类型 非常适合的任务。可以返回由编译器根据使用推断自动创建的类型的对象。

语法是这样的:

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

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

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

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

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

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

我觉得这能解决你的问题

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

所以,事情会是这样的:

.Select(i => new KeyValuePair<string, string>(i.category_id, i.category_name )).Distinct();
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);
}
}
}

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

也就是说 matchesList<(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();

也就是说 matchesList<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>