2016-07-25 72 views
-1

我有一個Array字節,表示圖像的RGB值。使用Linq將三個數組的項目分組爲

如何將這個數組的3個值(RGB)的每個偏移量分組來應用我的調整(如去除重複的顏色),也許使用Linq?

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

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

+1

這顯示了不同的方式來分塊列表:http://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq – hdz

+1

你可以使用Skeet的[morelinq庫](https:// github .com/morelinq/MoreLINQ)及其「Batch」方法。 –

回答

1

可以使用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>上的擴展方法)來更有效地執行此操作。

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值。

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] }); 
0

使用微軟的無框架小組的互動擴展(的NuGet 「IX-主」),你可以這樣做:

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 }