2011-09-06 30 views
8

biz, sırasıyla, her iki kod satırları yazılabilir İkinci satır ve ikinci kolonun toplamının bir toplamını elde etmek için pürüzlü bir diziDizi işlemleri

int[][] a = { new[] { 1, 2, 3, 4 }, new[] { 5, 6, 7, 8 }, new[] { 9, 10, 11, 12 } }; 

olduğunu varsayalım: biz 2-boyutlu bir dizi tanımına varsa

int rowSum = a[1].Sum(); 
int colSum = a.Select(row => row[1]).Sum(); 

Ancak

int[,] a = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; 

yukarıda belirtilen kod çalışmaz nedeniyle compiller hataları:

Error 1 Wrong number of indices inside []; expected 2 
Error 2 'int[*,*]' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'int[*,*]' could be found (are you missing a using directive or an assembly reference?) 

Yani, soru: pürüzlü olanları n boyutlu dizilerle LINQ yöntemleri kullanmak değil, nasıl? Dikdörtgen diziyi pürüzlü hale getirmek için bir yöntem nerede?

P.S. Cevabı belgede bulmayı denedim, ancak sonuç vermedi.

+0

Çok boyutlu diziler gerçekten (yoğun) – xanatos

cevap

15

LINQ to Objects, IEnumerable<T> Interface, yani tek boyutlu bir değerler dizisine dayanmaktadır. Bu mümkün olmamasına rağmen, pürüzlü olmayan diziler gibi n boyutlu veri yapıları ile iyi karışmaması anlamına gelir.

Sen tamsayılar tek boyutlu diziyi üretebilirsiniz n boyutlu diziye endeksi: "n boyutlu dizilerle LINQ yöntemlerini nasıl kullanılır" Sorunuzun Hakkında

int rowSum = Enumerable.Range(0, a.GetLength(1)).Sum(i => a[1, i]); 

int colSum = Enumerable.Range(0, a.GetLength(0)).Sum(i => a[i, 1]); 
+1

1 :-(C# desteklenmeyen aşağıda gibi yapıyor: İlginç bir yaklaşım –

3

:

You LINQ yöntemlerini boyutsal bir dizi ile kullanamazsınız, çünkü böyle bir dizi yalnızca IEnumerable uygular ancak IEnumerable<T> uygular ve LINQ uzantısı yöntemlerinin çoğu IEnumerable<T> için uzantı yöntemleridir.

Diğer soru hakkında: dtb'nin yanıtına bakın. DTB en çözümüne eklemek için

3

, dizinin tüm öğeleri yineleme daha genel bir şekilde olacaktır: şimdi

int[,] b = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; 

var flattenedArray = Enumerable.Range(0, b.GetLength(0)) 
        .SelectMany(i => Enumerable.Range(0, b.GetLength(1)) 
         .Select(j => new { Row = i, Col = j })); 

Ve:

var rowSum2 = flattenedArray.Where(t => t.Row == 1).Sum(t => b[t.Row, t.Col]); 
var colSum2 = flattenedArray.Where(t => t.Col == 1).Sum(t => b[t.Row, t.Col]); 

bu kadar ultra savurgan olduğunu Tabii Where ile filtrelemeye başlayacağımız öğeler için bile koordinat tuples oluşturuyoruz, ama seçim kriterlerinin ne olacağını önceden bilmiyorsanız, bu yol gitmek için bir yoldur (ya da değil - bu daha fazla bir egzersiz gibi görünüyor) pratikte yapmak istediğin bir şeyden daha iyi.

Ayrıca, bunun bir yinelemeli lambda ve Tuple gibi bir şey kullanarak herhangi bir rütbeli (sadece 2D değil) dizileri için nasıl genişletilebileceğini, ancak mazoşizmin topraklarına geçtiğini hayal edebiliyorum.

1

2D dizisinde, bir satır veya sütun üzerinde yinelenen yerleşik bir yolu yoktur. Gerçi kendi yönteminizi yaratmak çok zor değil. Satır ve sütun için numaralandırılabilir bir uygulama için bu sınıfı görün.

public static class LINQTo2DArray 
{ 
    public static IEnumerable<T> Row<T>(this T[,] Array, int Row) 
    { 
     for (int i = 0; i < Array.GetLength(1); i++) 
     { 
      yield return Array[Row, i]; 
     } 
    } 
    public static IEnumerable<T> Column<T>(this T[,] Array, int Column) 
    { 
     for (int i = 0; i < Array.GetLength(0); i++) 
     { 
      yield return Array[i, Column]; 
     } 
    } 
} 

Ayrıca a.Cast<int>() kullanarak diziyi dümdüz ancak sütunlar/satır

-1

en basit LINQ tek yaklaşım ben üzerinde satır ve sütun operasyonları bu tür yapmak görebilirsiniz hakkında tüm bilgiler daha sonra gevşek olur iki boyutlu dizi şu aramaları tanımlamaktır:

var firstColumnSum = cols[0].Sum(); 
:

var cols = a 
    .OfType<int>() 
    .Select((x, n) => new { x, n, }) 
    .ToLookup(xn => xn.n % a.GetLength(1), xn => xn.x); 

var rows = a 
    .OfType<int>() 
    .Select((x, n) => new { x, n, }) 
    .ToLookup(xn => xn.n/a.GetLength(1), xn => xn.x); 

Şimdi sadece bunu yapabilirsiniz

N boyutuna gelince, çok acı veriyor ... Üzgünüz.

0

basit bir yolu

var t = new List<Tuple<int, int>>(); 
int[][] a = t.Select(x => new int[]{ x.Item1, x.Item2}).ToArray();