Alan Wayne
Alan Wayne

Reputation: 5394

Using linq to find the leftmost and rightmost point in a jagged array?

I'm sure this is somewhere, but I can't find it.

I have a standard

StrokeCollection strokes

each stroke in the collection consisting of an array of points. Hence, this is jagged array of points, Point[][]

I need to find the leftmost and rightmost point in the StrokeCollection. How is this done with linq?

This is basically what I'm trying to do (without success):

var x = from stroke in strokes
           from point in stroke
         where min(point.x)
         select point

Any help would be much appreciated.

Edit: Apparently there are some problems with using ink stylus points directly, so let

 Point[][] myStrokeCollection = new Point[strokes.Count][];
            for (int i = 0; i < strokes.Count; i++)
            {
                // creating a one-dimensional array of StylusPoints for the i row of myStrokeCollection.
                myStrokeCollection[i] = new Point[strokes[i].StylusPoints.Count];
                for (int j = 0; j < strokes[i].StylusPoints.Count; j++)
                {
                    myStrokeCollection[i][j] = new Point();
                    myStrokeCollection[i][j].X = strokes[i].StylusPoints[j].X;
                    myStrokeCollection[i][j].Y = strokes[i].StylusPoints[j].Y;
                }
            }

Can a left most point(x,y) and right most point(x,y) be obtained with linq (in one pass?) for myStrokeCollection ? (Hopefully without defining additional types).

Upvotes: 1

Views: 541

Answers (3)

Alan Wayne
Alan Wayne

Reputation: 5394

From Sangram in chat, this works well:

var l1 = strokeCollection.SelectMany(p => p.StylusPoints) 
.GroupBy(p => p.X) 
.OrderBy(p => p.Key) 
.ToList(); 

StylusPoint leftPoint = l1.First().FirstOrDefault(); 
StylusPoint rightPoint = l1.Last().FirstOrDefault();

Upvotes: 1

Sangram Chavan
Sangram Chavan

Reputation: 351

Here is what needs to be done

    var leftMostVal = strokeCollection.Min(p => p.Point.Min(q => q.Min(r => r.X)));
    var rightMostVal = strokeCollection.Max(p => p.Point.Max(q => q.Max(r => r.X)));

Here is fiddle https://dotnetfiddle.net/y5hZ7w

Or 

       public class StrokeCollection : List<Stroke>
        {
        }

        public class Stroke : List<Point>
        {
            public Point[][] Points { get; set; }
        }
        class Program
        {
            static void Main(string[] args)
            {
                StrokeCollection lst = new StrokeCollection();


                Random rnd1 = new Random(3);
                Random rnd2 = new Random(13);


                for (int i = 0; i < 10; i++)
                {
                    int x = rnd1.Next(1, 5);
                    var s = new Stroke { Points = new Point[x][] };
                    foreach (var r in Enumerable.Range(0, x))
                    {
                        int y = rnd1.Next(1, 5);
                        s.Points[r] = new Point[y];

                        for (int j = 0; j < y; j++)
                            s.Points[r][j] = new Point(rnd2.Next(-50, 80), rnd2.Next(-20, 20));
                    }
                    lst.Add(s);
                }

                Point leftMostPoint = Point.Empty;
                Point rightMostPoint = Point.Empty;

                lst.ForEach(p1 =>
                {
                    foreach (Point[] p2 in p1.Points)
                    {
                        foreach (var p3 in p2)
                        {
                            if (leftMostPoint == Point.Empty)
                                leftMostPoint = p3;

                            if (rightMostPoint == Point.Empty)
                                rightMostPoint = p3;

                            if (p3.X < leftMostPoint.X)
                                leftMostPoint = p3;

                            if (p3.X > rightMostPoint.X)
                                rightMostPoint = p3;
                        }
                    }
                });

                Console.WriteLine("Leftmost point " + leftMostPoint.ToString());
                Console.WriteLine("Rightmost point " + rightMostPoint.ToString());
           }
       }

Edit : Update this is what you finally needed

    System.Windows.Ink.StrokeCollection strokeCollection; //Set it to whatever    resultant you want collection to set 

    var l1 = strokeCollection.SelectMany(p => p.StylusPoints) 
                             .GroupBy(p => p.X) 
                             .OrderBy(p => p.Key) 
                             .ToList(); 

StylusPoint leftPoint = l1.First().FirstOrDefault(); 
StylusPoint rightPoint = l1.Last().FirstOrDefault();

Upvotes: 2

Sai Puli
Sai Puli

Reputation: 971

(from stroke in strokeCollection
from point in stroke
group point by 1 into g
select new { Left = g.Min (p => p.x), Right = g.Max (p => p.x)}).FirstOrDefault();

https://dotnetfiddle.net/QONEqu

Upvotes: 1

Related Questions