Reputation: 5444
Let's say we have a Line
class defined by Point startPoint
and Point endPoint
.
If I have list of these lines, how can I extract all the points in them into one List<Point>
using LINQ.
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();
Upvotes: 3
Views: 2506
Reputation: 3705
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:
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:
lines.Select(o => o.StartPoint).Union(lines.Select(o => o.EndPoint)).ToList();
Upvotes: 1
Reputation: 5920
You can do this in a few different ways. One is to use 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
:
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
:
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
.
There are dozens of ways to achieve what you want. The real question is what do you want to do with this result later.
Upvotes: 1
Reputation: 27357
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.
However, you don't need to invoke ToList()
for each set, you can simply write:
var points = lines.Select(l => l.StartPoint).Concat(lines.Select(l => l.EndPoint)).ToList();
Upvotes: 6