Можете ли вы использовать LINQ или lambdas для выполнения матричных операций? - PullRequest
3 голосов
/ 23 ноября 2008

Я знаю, как это сделать, используя циклы for. Можно ли сделать что-то подобное, используя LINQ или lambdas?

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

Ответы [ 6 ]

6 голосов
/ 23 ноября 2008

РЕДАКТИРОВАТЬ: приведенный ниже код будет работать, но он не так удобочитаем, как при использовании явного метода. LINQ великолепен, когда он определенно добавляет к удобочитаемости ... но это не один из тех случаев.

Это более короткая версия ответа CMS - дополнительная let не требуется, а когда вы просто делаете проекцию, проще использовать точечную нотацию:

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

Альтернативой является использование формы Select, которая принимает индекс:

int[] result = a.Select((value, index) => value * b[index])
                .ToArray();
5 голосов
/ 23 ноября 2008

Использование функции Zip (новичок в .NET 4.0) подробнее здесь :

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

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

До выхода .NET 4 вы можете использовать реализацию zip по ссылке выше.

2 голосов
/ 23 ноября 2008

Нет ничего встроенного, но вы всегда можете написать свои собственные функции. Первый из них - это простой метод расширения, который делает то, что вы хотите. Второй позволяет указать функцию для применения:

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;
    }
}
2 голосов
/ 23 ноября 2008

Вы можете сделать что-то вроде этого:

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 , существует множество там ...

0 голосов
/ 03 июня 2017

Вы можете написать простое расширение, которое работает с матрицами любого ранга.

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);
0 голосов
/ 23 ноября 2008

Ознакомьтесь с этой статьей MSDN о готовящемся PLINQ (Parallel LINQ). Из статьи приведен пример использования PLINQ для распараллеливания умножения матриц:

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 и Lambda! И в качестве бонуса он распространяется на процессоры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...