2008-11-23 4 views
3

Je sais comment faire cela en utilisant des boucles. Est-il possible de faire quelque chose comme ça en utilisant LINQ ou lambdas?Pouvez-vous utiliser LINQ ou lambdas pour effectuer des opérations matricielles?

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

mais pourquoi voudriez-vous utiliser LINQ? Qu'est-ce qui ne va pas avec une boucle de confiance que tout le monde peut comprendre? –

+0

... ou simplement utiliser une bibliothèque de classes Matrix ... –

+0

Assez drôle, j'ai [répondu à une autre question aujourd'hui] (http://stackoverflow.com/questions/311710/how-do-i-sum-a-list- of-arrays # 311863) qui somme les nombres en place dans deux séquences. –

Répondre

6

EDIT: Le code ci-dessous fonctionnera, mais il n'est pas aussi lisible que l'utilisation d'une méthode explicite. LINQ est génial où il ajoute à la lisibilité ... mais ce n'est pas un de ces cas.

C'est une version plus brève de la réponse de la CMS - le let supplémentaire n'est pas nécessaire, et quand vous faites juste une projection, il est plus simple d'utiliser simplement la notation de points:

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

Une alternative est d'utiliser la forme de Select qui prend un indice:

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

@Jon: vous n'encouragez certainement pas les gens à le faire de cette façon! –

+0

@Mitch: Bon point. Modification ... –

+0

@Jon: juste remarqué que vous avez atteint la barre des 1000 réponses. Joli! –

2

Vous pouvez faire quelque chose comme ceci:

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(); 
} 

Mais je vous recommande si vous travaillerez avec des matrices et des sujets mathématiques plus avancés pour obtenir une bonne bibliothèque de mathématiques, comme NMath ou rechercher un Matrix class mise en œuvre, il y en a beaucoup là-bas ...

2

Il n'y a rien intégré, mais vous pouvez toujours écrire vos propres fonctions. Le premier ci-dessous est une méthode d'extension simple faisant ce que vous voulez. La seconde vous permet de spécifier la fonction à appliquer:

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

Vérifiez cette MSDN article on the upcoming PLINQ (Parallel LINQ). De l'article, voici un exemple d'utilisation PLINQ à paralléliser multiplication matricielle:

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

Il utilise LINQ et Lambda! Et en prime, il est réparti entre les processeurs.

+0

En fait, il utilise la bibliothèque TPL (Task Parallel Library) et les délégués (pas Lambda). –

5

Utilisation de la fonction Zip (nouveau à .NET 4.0) détails here:

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

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

Jusqu'à ce que .NET 4 sorte, vous pouvez utiliser l'implémentation zip à partir du lien ci-dessus.

0

Vous pouvez écrire une extension simple qui fonctionne avec des matrices de n'importe quel rang.

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 
    } 
} 

Voici quelques valeurs de test:

// 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); 
Questions connexes