简体   繁体   English

使用Linq选择多个属性

[英]Select more than one property using Linq

Let's say we have a Line class defined by Point startPoint and Point endPoint . 假设我们有一个由Point startPointPoint endPoint定义的Line类。

If I have list of these lines, how can I extract all the points in them into one List<Point> using LINQ . 如果我有这些行的列表,如何使用LINQ将它们中的所有点提取到一个List<Point>中。

This is what I have so far: 这是我到目前为止的内容:

IList<Point> points1 = lines.Select(o => o.StartPoint).ToList();
IList<Point> points2 = lines.Select(o => o.EndPoint).ToList();

IList<Point> points = points1.Concat(points2).ToList();

If you want a shorter way, you can do something like this: 如果您想使用更短的方法,可以执行以下操作:

var points = lines.SelectMany(l => new[] { l.StartPoint, l.EndPoint }).ToList();

However, your current code is debateably more readable, but more importantly, does not create an array for each line you iterate. 但是,您当前的代码具有更好的可读性,但更重要的是,它不会为您迭代的每一line创建一个数组。

However, you don't need to invoke ToList() for each set, you can simply write: 但是,您不需要为每个集合调用ToList() ,只需编写即可:

var points = lines.Select(l => l.StartPoint).Concat(lines.Select(l => l.EndPoint)).ToList();

You can do this in a few different ways. 您可以通过几种不同的方式来执行此操作。 One is to use Tuple<Point, Point> : 一种是使用Tuple<Point, Point>

IEnumerable<Tuple<Point, Point>> r = lines.Select(l => new Tuple<Point, Point>(l.StartPoint, l.EndPoint));

To access these then you have to keep in mind that StartPoint would be Item1 and EndPoint will be Item2 : 要访问这些文件,您必须记住StartPoint将是Item1EndPoint将是Item2

foreach ( Tuple<Point, Point> se in r )
{
    var start = se.Item1;
    var end   = se.Item2;
}

Another one could be to make an array of 2 elements each : 另一个可能是使每个元素包含两个元素:

IEnumerable<Point[]> r = lines.Select(l => new Point[2]{ l.StartPoint, l.EndPoint });

To access these you have to keep in mind that index 0 contains your StartPoint and index 1 contains your EndPoint : 要访问它们,必须记住索引0包含您的StartPoint ,索引1包含您的EndPoint

foreach( Point[] parr in r )
{
    if( parr.Length == 2 )
    {
        var start = parr[0];
        var end   = parr[1];
    }
}

You can always create a flat model containing only these two properties and then just cast/create it in the Select . 您始终可以创建仅包含这两个属性的平面模型,然后在Select铸造/创建。

There are dozens of ways to achieve what you want. 有很多方法可以实现您想要的。 The real question is what do you want to do with this result later. 真正的问题是您以后要如何处理此结果。

Your solution is the closer you can get to it. 您的解决方案离您越近。 If you don't want to enumerate twice the list you should go for a Foreach/Map approach: 如果您不想对列表进行两次枚举,则应采用Foreach / Map方法:

var points = new List<Point>();

lines.Map(line =>
{
     points.Add(line.startPoint);
     points.Add(line.EndPoint);
 } );

If you don't want to use Concat you can use Union: 如果您不想使用Concat,则可以使用Union:

lines.Select(o => o.StartPoint).Union(lines.Select(o => o.EndPoint)).ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM