2008-11-23 7 views
3

for 루프를 사용하여이 작업을 수행하는 방법을 알고 있습니다. LINQ 또는 lambdas를 사용하여 이와 같은 작업을 수행 할 수 있습니까?LINQ 또는 lambda를 사용하여 행렬 연산을 수행 할 수 있습니까?

int[] a = { 10, 20, 30 }; 
int[] b = { 2, 4, 10 }; 
int[] c = a * b; //resulting array should be { 20, 80, 300 } 
+0

그런데 왜 당신도 LINQ를 사용할까요? 모든 사람들이 이해할 수있는 믿을만한 'for loop'의 문제점은 무엇입니까? –

+0

... 아니면 그냥 매트릭스 클래스 라이브러리를 사용 ... –

+0

웃기지 만, 나는 [다른 질문에 오늘 응답] (http://stackoverflow.com/questions/311710/how-do-i-sum-a-list- of-arrays # 311863) 두 개의 순서로 숫자를 합산합니다. –

답변

6

편집 : 아래 코드는 작동하지만 명시적인 방법을 사용하는 것처럼 읽을 수 없습니다. LINQ는 확실히 이 가독성에을 추가하는 곳에서 훌륭합니다. 그러나이 경우는 아닙니다.

int[] result = Enumerable.Range(0, a.Length) 
         .Select(i => a[i] * b[i]) 
         .ToArray(); 

대안은 사용하는 것입니다 : 여분의 let이 필요하지 않습니다, 당신은 단지 프로젝션을 수행 할 때 그것은 단지 점 표기법을 사용하는 간단 -

는 CMS의 대답의 짧 버전입니다 인덱스 소요 선택의 형태 :

int[] result = a.Select((value, index) => value * b[index]) 
       .ToArray(); 
+0

@ 존 : 물론 당신은 사람들이 이런 식으로 할 것을 권장하지 않습니다! –

+0

@Mitch : 좋은 지적. 편집 중 ... –

+0

@ 존 : 방금 1000 개의 답을 얻은 것으로 나타났습니다. 좋은 분! –

2

이 같은 수행 할 수 있습니다

int[] a = {10, 20, 30}; 
int[] b = {2, 4, 10}; 

if (a.Length == b.Length) 
{ 
    int[] result = (from i in Enumerable.Range(0, a.Length) 
      let operation = a[i]*b[i] 
     select operation).ToArray(); 
} 

을하지만 NMath처럼, 좋은 수학 라이브러리를 얻을 행렬 및 고급 수학 주제로 작업 또는 Matrix class를 검색 할 경우 당신을 추천합니다 구현, 거기 밖으로 많은 ...

2

거기에 아무것도 내장되어 있지만, 당신은 항상 자신의 기능을 쓸 수 있습니다. 아래의 첫 번째 방법은 원하는 것을하는 간단한 확장 방법입니다.

class Program 
{ 
    public static void Main(string[] args) 
    { 
     int[] a = { 10, 20, 30 }; 
     int[] b = { 2, 4, 10 }; 
     int[] c = a.MatrixMultiply(b); 
     int[] c2 = a.Zip(b, (p1, p2) => p1 * p2); 
    } 
} 

public static class Extension 
{ 
    public static int[] MatrixMultiply(this int[] a, int[] b) 
    { 
     // TODO: Add guard conditions 
     int[] c = new int[a.Length]; 
     for (int x = 0; x < a.Length; x++) 
     { 
      c[x] = a[x] * b[x]; 
     } 
     return c; 
    } 

    public static R[] Zip<A, B, R>(this A[] a, B[] b, Func<A, B, R> func) 
    { 
     // TODO: Add guard conditions 
     R[] result = new R[a.Length]; 
     for (int x = 0; x < a.Length; x++) 
     { 
      result[x] = func(a[x], b[x]); 
     } 
     return result; 
    } 
} 
0

체크 아웃이 MSDN article on the upcoming PLINQ (병렬 LINQ) : 두 번째는 당신이 적용 할 기능을 지정할 수 있습니다.

void ParMatrixMult(int size, double[,] m1, double[,] m2, double[,] result) 
{ 
    Parallel.For(0, size, delegate(int i) { 
    for (int j = 0; j < size; j++) { 
     result[i, j] = 0; 
     for (int k = 0; k < size; k++) { 
     result[i, j] += m1[i, k] * m2[k, j]; 
     } 
    } 
    }); 
} 

그것은 LINQ 및 람다를 사용하고 : 기사에서, 여기 병렬화 행렬 곱셈을 PLINQ를 사용하는 예입니다! 보너스로 프로세서를 통해 보급됩니다.

+0

사실 TPL (Task Parallel Library)과 델리게이트 (Lambda가 아닙니다)를 사용합니다. –

5

(.NET 4.0 새)를 우편 기능을 사용하여이 here 자세한 사항 :

int[] a = { 10, 20, 30 }; 
int[] b = { 2, 4, 10 }; 

int[] c = a.Zip(b, (a1, b1) => a1 * b1).ToArray(); 

.NET 4가 나올 때까지 위 링크의 zip 구현을 사용할 수 있습니다.

0

임의의 순위의 행렬에서 작동하는 간단한 확장을 작성할 수 있습니다. 여기

public static class TwodimensionalArrayExtensions 
{ 
    public static int[][] MultiplyBy(this int[][] leftMatrix, int[][] rightMatrix) 
    { 
     if (leftMatrix[0].Length != rightMatrix.Length) 
     { 
      return null; // Matrices are of incompatible dimensions 
     } 

     return leftMatrix.Select(// goes through <leftMatrix matrix> row by row 

       (leftMatrixRow, leftMatrixRowIndexThatIsNotUsed) => 

        rightMatrix[0].Select(// goes through first row of <rightMatrix> cell by cell 

          (rightFirstRow, rightMatrixColumnIndex) => 

           rightMatrix 
            .Select(rightRow => rightRow[rightMatrixColumnIndex]) // selects column from <rightMatrix> for <rightMatrixColumnIndex> 
            .Zip(leftMatrixRow, (rowCell, columnCell) => rowCell * columnCell) // does scalar product 
            .Sum() // computes the sum of the products (rowCell * columnCell) sequence. 
         ) 
         .ToArray() // the new cell within computed matrix 
      ) 
      .ToArray(); // the computed matrix itself 
    } 
} 

는 몇 가지 테스트 값은 다음과 같습니다

// Test1 
int[][] A = { new[] { 1, 2, 3 } }; 
int[][] B = { new[] { 1 }, new[] { 2 }, new[] { 3 } }; 
int[][] result = A.MultiplyBy(B); 

// Test2 
int[][] A = { new[] { 1 }, new[] { 2 }, new[] { 3 } }; 
int[][] B = { new[] { 1, 2, 3 } }; 
int[][] result = A.MultiplyBy(B); 

// Test3 
int[][] A = new int[][] { new[] { 1, 2 }, new[] { 2, 2 }, new[] { 3, 1 } }; 
int[][] B = new int[][] { new[] { 1, 1, 1 }, new[] { 2, 3, 2 } }; 
int[][] result = A.MultiplyBy(B);