你可以使用LINQ或lambdas来执行矩阵运算吗?

时间:2008-11-23 04:07:58

标签: c# linq lambda

我知道如何使用for循环执行此操作。是否可以使用LINQ或lambdas做这样的事情?

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

7 个答案:

答案 0 :(得分:6)

编辑:下面的代码可以使用,但它不像使用显式方法那样可读。 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();

答案 1 :(得分:5)

使用Zip功能(.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实现。

答案 2 :(得分: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实现,那里有很多...

答案 3 :(得分: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;
    }
}

答案 4 :(得分:0)

查看此MSDN article on the upcoming PLINQ(并行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!作为奖励,它分散在处理器之间。

答案 5 :(得分:0)

您可以编写一个适用于任何等级矩阵的简单扩展。

<?php
  $str = '{
    "users": [
        {
            "steamid": "[X:X:XXXXXXXXX]",
            "teamspeakid": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            "nicknames": [
                "XXXXXXXXX"
            ],
            "addresses": [
                "XX.XX.XXX.XX"
            ]
        },
        {
            "steamid": "[Y:Y:YYYYYYYYY]",
            "teamspeakid": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
            "nicknames": [
                "YYYYYYYYY"
            ],
            "addresses": [
                "YY.YY.YYY.YY"
            ]
        },
        {
            "steamid": "[Z:Z:ZZZZZZZZZ]",
            "teamspeakid": "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
            "nicknames": [
                "ZZZZZZZZZ"
            ],
            "addresses": [
                "ZZ.ZZ.ZZZ.ZZ"
            ]
        }

    ]
}';

$json = json_decode($str);
foreach($json->users as $item)
{
    if($item->steamid == "[X:X:XXXXXXXXX]")
    {
        echo $item->addresses;
    }
}

?>

以下是一些测试值:

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

答案 6 :(得分:0)

如果事先对正确的矩阵进行转置,乘法可以更优雅地表达如下。

int[][] Multiply(int[][] left, int[][] right) =>
    left.Select(lr => 
            right
                .Select(rr => 
                    lr.Zipped(rr, (l, r) => l * r).Sum())
                .ToArray())
        .ToArray();