我有一个Point集合,存储在PointCollection中。
我需要集合中的点来绘制线条。因此,例如,如果一个点集合有四个点,那将是两行,因为我使用集合中的点对来绘制线。我正在寻找一种方法,最好使用linq,尽可能少的代码行,基本上迭代我的PointCollection,提取下一对可用的点,然后使用点对绘制线。有没有办法使用linq,lambda表达式或扩展方法?
感谢。
答案 0 :(得分:1)
这是快速获取代码的代码。
var listOfPairs = points
.Select((p, i) => new {p, i})
.GroupBy(x => x.i / 2)
.Where(g => g.Skip(1).Any())
.Select(g => g.Select(x => x.p).ToList())
.ToList();
与foreach循环相比,如果你有数千个点,那么这不具备效果。
这是另一个请求的表单,使用捕获的变量。
Point previous = points.FirstOrDefault();
List<Pair> pairs = points
.Skip(1)
.Select(p =>
{
Pair result = new Pair(p, previous)
previous = p;
return result;
})
.ToList();
答案 1 :(得分:1)
假设您没有在foreach上使用并行性,可以使用:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
namespace PointDrawing
{
class Program
{
static void Main(string[] args)
{
List<Point> points = new List<Point>();
points.Add(new Point(1, 1));
points.Add(new Point(2, 2));
points.Add(new Point(3, 3));
points.Add(new Point(4, 4));
points.Add(new Point(5, 5));
points.Add(new Point(6, 6));
points.Add(new Point(7, 7));
if (points.Count > 0)
{
Point src = points[0];
points.ForEach(p => Draw(ref src, p));
}
}
public static void Draw(ref Point p1, Point p2)
{
if (p1 != p2)
{
//Draw from p1 to p2 here
}
p1 = p2; //assign so that p2 is the next origin
}
}
}
这可以使用一个点列表,但如果PointCollection是一个IEnumerable,你总是可以为你的IEnumerables添加如此有用的ForEach扩展:
public static class Extensions
{
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var item in source)
{
action(item);
}
}
}
答案 2 :(得分:0)
假设你只想要顺序对(注意这不是绘制它们 - 它只是列出它们):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
static class Program {
static void Main() {
PointCollection points = new PointCollection();
points.Add(new Point(1, 1));
points.Add(new Point(2, 2));
points.Add(new Point(3, 3));
points.Add(new Point(4, 4));
points.Add(new Point(5, 5));
points.Add(new Point(6, 6));
points.Add(new Point(7, 7)); // odd number to test end
foreach (Tuple<Point, Point> pair in GetPairs(points)) {
Console.WriteLine("From " + pair.Value1 + " to " + pair.Value2);
}
}
public static IEnumerable<Tuple<Point, Point>>
GetPairs(PointCollection points) {
using (IEnumerator<Point> iter = points.GetEnumerator()) {
while (iter.MoveNext()) {
Point value1 = (Point)iter.Current;
if (!iter.MoveNext()) { yield break; }
yield return new Tuple<Point, Point>(value1, (Point)iter.Current);
}
}
}
}
public struct Tuple<T1, T2> {
public T1 Value1 { get { return value1; } }
public T2 Value2 { get { return value2; } }
private readonly T1 value1;
private readonly T2 value2;
public Tuple(T1 value1, T2 value2) {
this.value1 = value1;
this.value2 = value2;
}
}
答案 3 :(得分:0)
另一种方法,使用一点LINQ和递归:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace overflow2
{
class Program
{
static void Main(string[] args)
{
List<Point> points = new List<Point>();
points.Add(new Point(1, 1));
points.Add(new Point(2, 2));
points.Add(new Point(3, 3));
points.Add(new Point(4, 4));
points.Add(new Point(5, 5));
points.Add(new Point(6, 6));
points.Add(new Point(7, 7)); // odd number to test end
foreach (LineSegment<Point> linesegment in points.GetPairs())
Console.WriteLine("From " + linesegment.Value1.ToString() + " to " + linesegment.Value2.ToString());
Console.ReadLine();
}
}
public class Point
{
public int x { get; set; }
public int y { get; set; }
public Point(int _x, int _y)
{
x = _x;
y = _x;
}
public override string ToString()
{
return string.Format("{0},{1}", x, y);
}
}
public class LineSegment<T>
{
public T Value1 { get; private set; }
public T Value2 { get; private set; }
public LineSegment(T value1, T value2)
{
Value1 = value1;
Value2 = value2;
}
}
public static class Util
{
public static List<LineSegment<Point>> GetPairs(this List<Point> points)
{
if (points.Count >= 2)
{
var pair = new LineSegment<Point>(points.Take(1).First(), points.Skip(1).Take(1).First());
var res = new List<LineSegment<Point>>() { pair };
res.AddRange(points.Skip(2).ToList().GetPairs()); // recursion
return res;
}
else
return new List<LineSegment<Point>>();
}
}
}