LINQ转换数组[x0,y0,…], xN, yN] into enumerable [p0,…], pN]

本文关键字:into enumerable p0 pN yN xN 数组 y0 LINQ 转换 x0 | 更新日期: 2023-09-27 18:01:23

是否可以使用LINQ来转换包含坐标元组(x, y)的双精度对象的平面数组?(x0, y0,…, xN, yN]转换为包含相同坐标的一半长度的数组,用Point -类封装,即[p0,…], pN) ?

最好是。net 3.5,但也对4.0感兴趣。

LINQ转换数组[x0,y0,…], xN, yN] into enumerable [p0,…], pN]

你可以从Jon Skeet的morelinq:

使用.Batch
IEnumerable<Point> points = coordinates.Batch(2,pair => new Point(pair.ElementAt(0), pair.ElementAt(1)));

老实说,最简单的解决方案可能是使用一个方法(这里是int s):

public IEnumerable<Point> GetPoints(int[] coordinates)
{
    for (int i = 0; i < coordinates.Length; i += 2)
    {
        yield return new Point(coordinates[i], coordinates[i + 1]);
    }
}
double[] arr = { 1d, 2d, 3d, 4d, 5d, 6d };
var result = arr.Zip(arr.Skip(1), (x, y) => new Point(x, y))
                .Where((p, index) => index % 2 == 0);

EDIT:在这个LINQ语句中,集合循环两次,效率不高。一个更好的解决方案是使用for环路。Zip在c# 4.0中是新的,另一种选择是:

var result = arr.Select((n, index) => new Point(n, arr[index + 1]))
                .Where((p, index) => index % 2 == 0);

这将只循环一次,并将在3.5

        int[] arr = new int[] { 1, 1, 2, 2, 3, 3 };
        if (arr.Length % 2 != 0)
            throw new ArgumentOutOfRangeException();
        Point[] result = arr
                        .Where((p, index) => index % 2 == 0)
                            .Select((n, index) => new Point(n, arr[index * 2 + 1]))
                               .ToArray();

还有另一个选项(可能更"纯粹"):

public static class Program
{
    public static IEnumerable<Point> ToPoints(this IEnumerable<int> flat)
    {
        int idx = 0;
        while(true)
        {
            int[] parts = flat.Skip(idx).Take(2).ToArray();
            if (parts.Length != 2)
                yield break;
            idx += 2;
            yield return new Point(parts[0], parts[1]);
        }
    }
    static void Main(string[] args)
    {
        int[] arr = new int[] { 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
        var x = arr.ToPoints().ToArray();
        return;
    }

}

当然。我没有编译/运行,所以它可能有拼写错误,但要点应该是正确的。

var newArray = source.Aggregate(new List<double>, 
     (xCoords, next) => 
        {
           if(xCoords.length % 2 == 0) {
              xCoords.Add(next);
           }
           return xCoords;
        },
     xCoords => xCoords
     ).Zip(source.Aggregate(new List<double>, 
        (yCoords, next) => 
           {
              if(yCoords.length % 2 != 0) {
                 yCoords.Add(next);
              }
              return yCoords;
           },
        yCoords => yCoords
    , (x, y) => new Point(x, y)
    ).ToArray();