使用Linq将数组项目分组

时间:2016-07-25 01:41:40

标签: c# arrays linq

我有Array个字节,表示图像的RGB值。

如何对这个数组的3个值(RGB)的每个偏移进行分组以应用我的调整(比如删除重复的颜色),也许使用Linq?

["120", "100", "10", "120", "100", "10", "10", "60", "110"]

["120", "100", "10", "10", "60", "110"]

4 个答案:

答案 0 :(得分:2)

您可以使用Select为枚举添加索引,然后按index / 3添加组。对每个组进行一些后处理,你应该能够得到你想要的东西:

var grouped = source.Select((x,i) => new { x, i })
                    .GroupBy(x -> x.i / 3)
                    .Select(g => g.ToList())
                    .Select(g => new { R = g[0], G = g[1], B = g[2] })
                    .Distinct();

但这感觉非常难看。如果我是你,我可能会编写一个简单的自定义LINQ方法(IEnumerable<int>上的扩展方法)来更有效地执行此操作。

答案 1 :(得分:1)

获取不同RGB值及其索引的较短版本:

string[] a = { "120", "100", "10", "120", "100", "10", "10", "60", "110" };

var l = Enumerable.Range(0, a.Length / 3)
                   .ToLookup(i => new { R = a[i * 3], G = a[i * 3 + 1], B = a[i * 3 + 2] });

答案 2 :(得分:0)

如果您不介意使用循环而不是Linq:

class Program
{
    static void Main(string[] args)
    {
        byte[] array = new byte[] { 120, 100, 10, 120, 100, 10, 10, 60, 110 };
        List<byte[]> grouped = new List<byte[]>();


        // This loop will populate the list grouped with arrays of 3 bytes each, each representing an value for RGB
        for(int i = 0; i + 2 < array.Length; i += 3)
        {
            byte[] currentColor = new byte[]
            {
                array[i],
                array[i + 1],
                array[i + 2]
            };

            grouped.Add(currentColor);
        }

        // Here you will remove repeated elements for RGB
        // Notice you will have to create the ByteArrayComparer class, you will find the code right under this one
        var noRepeatedElements = grouped.Distinct<byte[]>(new ByteArrayComparer());

        // Print the non repeated elements for testing purposes
        foreach(var rgb in noRepeatedElements)
        {
            foreach(var value in rgb)
            {
                Console.Write($"\"{value}\"");
            }
        }

        Console.ReadKey();
    }
}

其中ByteArrayComparer是以下类

// This class will compare two distinct byte arrays and check if their elements are the same
public class ByteArrayComparer : IEqualityComparer<byte[]>
{
    public bool Equals(byte[] x, byte[] y)
    {
        int smallerArrayLength = Math.Min(x.Length, y.Length);
        bool elementsWithSameValue = true;

        for(int i = 0; i < smallerArrayLength; i++)
        {
            // If there is a single element which is different, we know the arrays are different and can break the loop.
            if(x[i] != y[i])
            {
                elementsWithSameValue = false;
                break;
            }
        }

        return elementsWithSameValue;
    }

    public int GetHashCode(byte[] obj)
    {
        int hash = 0;

        for(int i = 0; i < obj.Length; i++)
        {
            hash += obj[i].GetHashCode();
        }

        return hash;
    }
}    

请注意,分组现在是一个字节数组列表。 分组中的每个元素都有三个元素,表示单个RGB值。

现在您可以随意使用rgb值。

答案 3 :(得分:0)

使用Microsoft的Reactive Framework团队的交互式扩展程序(NuGet&#34; Ix-Main&#34;),您可以这样做:

byte[] array = new byte[]
{
    120, 100, 10, 120, 100, 10, 10, 60, 110
};

byte[] results =
    array
        .Buffer(3)
        .Distinct(xs => String.Join(",", xs))
        .SelectMany(x => x)
        .ToArray();

这会给你{ 120, 100, 10, 10, 60, 110 }