从PointCollection中检索点对?

时间:2010-01-13 05:35:13

标签: c# linq

我有一个Point集合,存储在PointCollection中。

我需要集合中的点来绘制线条。因此,例如,如果一个点集合有四个点,那将是两行,因为我使用集合中的点对来绘制线。我正在寻找一种方法,最好使用linq,尽可能少的代码行,基本上迭代我的PointCollection,提取下一对可用的点,然后使用点对绘制线。有没有办法使用linq,lambda表达式或扩展方法?

感谢。

4 个答案:

答案 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>>();
        }
    }
}