【问题标题】:Can LINQ construct and return a multidimensional arrayLINQ可以构造并返回多维数组吗
【发布时间】:2014-12-01 16:52:03
【问题描述】:

是的,我确实知道锯齿数组 [][] 和多维数组 [,] 之间的区别。

是的,我已经查找了重复项并找到了这些:

其中最后一个包含完成这项工作的功能。但我的问题仍然是:有什么方法(无论多么扭曲或做作)来说服 LINQ 以多维数组的形式构造并返回结果(而不是锯齿状数组)?


这与问题并不真正相关,但这里导致的问题是那些看起来像是“为 LINQ 制作”的小工作之一,除了我需要调用的函数是用多维数组参数定义的.将答案生成为锯齿状数组的 LINQ 代码花了大约 5 分钟来编写,然后呢?我错过了什么,还是真的没有办法 LINQ 来完成这项工作?


我想我应该说:除了编写一大段代码以旧方式执行并将其嵌入为 lambda 或将其作为扩展方法调用。目前看来,LINQ 似乎既不能生成也不能使用多维数组,而我的问题的答案是否定的。

【问题讨论】:

  • 我不确定你的目标是什么。如果您发布的最后一个链接的答案有效,那么为什么不简单地将其转换为扩展方法,以便您可以像 .Where(...).Select(...).ToRectangularArray() 一样使用它呢?或者你想让from x in xs select x.y返回一个多维数组而不是IEnumerable
  • Linq 与 IEnumerables 一起使用。它的所有返回类型都是 IEnumerable 的某种风格。如果您想返回一个多维数组,那么我想您必须编写一个等效于 Enumerable.ToArray() 的当前不存在的数组。

标签: c# .net arrays linq multidimensional-array


【解决方案1】:

嗯..好吧..确定吗?这是一个如何将整数列表转换为二维数组的示例。

void Main()
{
    var wat = new[]{2, 4, 5, 6, 7, 8}
        .Select(x => new { dummy=1, val= x})
        .GroupBy(x => x.dummy) // group everything into one, "UNFLATTEN"
        .Select(gr => 
            {
                var elements = gr.Select(x => x.val).ToList();
                if(elements.Count == 0 || elements.Count % 2 != 0)
                    throw new NotSupportedException("I don't know what to do.");

                var halfSize = elements.Count / 2;

                int[,] ret = new int[2, halfSize];

                for(var k = 0; k < halfSize; k++){
                    ret[0, k] = elements[k];
                    ret[1, k] = elements[elements.Count - halfSize + k];
                }

                return ret;
            }
        ).First();

    wat.Dump();
}

输出:

_ 0 1 2

0 2 4 5

1 6 7 8

正如其他人所说,您最好创建新的扩展方法:

static class LinqExtensions
{
    public static T[,] ToRectangularArray<T>(this IEnumerable<IEnumerable<T>> arrays)
    {
        // TODO: Validation and special-casing for arrays.Count == 0
        // TODO: Rename "arrays"
        // TODO: Make sure that Count() is used only once,
        // TODO: ElementAt() does not work everywhere, you're better off using ToList() before!
        int minorLength = arrays.First().Count();
        T[,] ret = new T[arrays.Count(), minorLength];
        for (int i = 0; i < arrays.Count(); i++)
        {
            var array = arrays.ElementAt(i);
            if (array.Count() != minorLength)
            {
                throw new ArgumentException
                    ("All arrays must be the same length");
            }
            for (int j = 0; j < minorLength; j++)
            {
                ret[i, j] = array.ElementAt(j);
            }
        }
        return ret;
    }
}

void Main()
{
    var wat = new[]{new[]{2, 4, 5}, new[]{6, 7, 8}}.ToRectangularArray();
    wat.Dump();
}

为方便起见,您可能想为IEnumerable&lt;T&gt; 添加相同的扩展方法,并调用它:ToRectangularArray&lt;T&gt;(this IEnumerable&lt;T&gt; input, int dimensions = 2)

【讨论】:

  • 纯粹的独创性必须值得+1,但这确实不是我的想法。见编辑。
  • 我理解你的感受。 .NET 框架实际上缺少 1000 件本应存在的东西。好消息是;如果你很聪明,你现在再也不必面对这个问题了,因为你把它添加到了你自己的“迷你体验库”中,不好的是:其他人必须面对这个问题。帮助和发展社区,您可以编写方法和单元测试,并要求 Jon 将其拉入 MoreLINQ :-)。至于您的“真正问题”,正如您所说,答案是否定的。
  • 好评。我并不真正在那个社区中,但希望其他人可以接受并使用它。
【解决方案2】:

我想我应该说:除了写一大段代码来做这件事 旧方法并将其嵌入为 lambda 或将其称为扩展 方法。现在看起来好像 LINQ 既不能生成也不能生成 消耗多维数组,我的问题的答案是否定的。

不是。大多数 LINQ 方法是IEnumerable&lt;T&gt; 的扩展方法。虽然锯齿数组(例如,int[int[]])实现了IEnumerable&lt;int[]&gt;,但多维数组却没有实现IEnumerable&lt;T&gt;,因此您不能使用任何LINQ 扩展方法。

您唯一能做的就是最终使用投影返回一个多维数组 (Select)。

【讨论】:

  • 谢谢。我很确定这是出于正确原因的正确答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 2010-11-23
  • 2020-06-10
  • 1970-01-01
  • 2016-10-21
  • 1970-01-01
相关资源
最近更新 更多