【问题标题】:How can I convert a list<> to a multi-dimensional array?如何将 list<> 转换为多维数组?
【发布时间】:2009-03-24 16:29:12
【问题描述】:

我有以下方法签名:

public void MyFunction(Object[,] obj)

我创建了这个对象:

List<List<Object>> obj = new List<List<Object>>;

有没有一种简单的方法可以将其转换为Object[,]


更新:

事实上,我喜欢使用Lists,因为我可以轻松添加新项目。有没有办法可以声明我的 List&lt;&gt; 对象来满足这种需求?我知道Object[,] 中的列数,但不知道行数。

【问题讨论】:

  • 是否可以选择使用锯齿状数组 (T[][])?因为它可以让代码更简单(您可以在内部级别使用 List.ToArray())。

标签: c# .net arrays list


【解决方案1】:

没有。事实上,这些不一定是兼容的数组。

[,] 定义了一个多维数组。 List&lt;List&lt;T&gt;&gt; 将更多地对应于锯齿状数组 (object[][])。

问题在于,对于您的原始对象,列表列表中包含的每个 List&lt;object&gt; 可以具有不同数量的对象。您需要制作一个内部列表最大长度的多维数组,并用空值填充或类似的东西以使其匹配。

【讨论】:

  • 看起来你的一些文字被吃掉了。您应该使用 而不是文字尖括号。
  • 尽管如此,有充分的理由想要这样做,即使源数据(在嵌套列表中)永远无法“锯齿状”。原因是 T[,] 没有实现 IEnumerable 但 T[][] 确实......看到这个问题:stackoverflow.com/questions/2562817/…
【解决方案2】:

你不会得到一个非常简单的解决方案(即几行)。在这种情况下,LINQ/Enumerable 类不会为您提供帮助(尽管如果您想要一个锯齿状数组,即Object[][],它可以帮助您)。在这种情况下,普通的嵌套迭代可能是最好的解决方案。

public static T[,] To2dArray(this List<List<T>> list)
{
    if (list.Count == 0 || list[0].Count == 0)
        throw new ArgumentException("The list must have non-zero dimensions.");

    var result = new T[list.Count, list[0].Count];
    for(int i = 0; i < list.Count; i++)
    {
        for(int j = 0; j < list[i].Count; j++)
        {
            if (list[i].Count != list[0].Count)
                throw new InvalidOperationException("The list cannot contain elements (lists) of different sizes.");
            result[i, j] = list[i][j];
        }
    }

    return result;
}

我在函数中包含了一些错误处理,只是因为如果您在非方形嵌套列表中使用它可能会导致一些令人困惑的错误。

这种方法当然假设每个List&lt;T&gt; 包含作为父List 的元素的长度相同。 (否则你真的需要使用锯齿状数组。)

【讨论】:

  • 我已经得到了像你这样的东西,但我希望有一种更快的方法可以做到这一点,无论如何你的解决方案更通用!
  • 是的,没问题。虽然我可能是错的,但你不会得到比这更简单的东西。如果您决定改用锯齿状数组,那么我当然可以建议使用 LINQ/扩展方法解决方案。
  • 唯一能让它更简单的方法是,如果你想使用最大尺寸并留下空单元格。
  • 为了记录,锯齿状数组非常容易:objects.Select(subObjects => subObjects.ToArray()).ToArray();
  • @Samuel:是的,这正是我的建议。
【解决方案3】:

这是使用 Linq 的 Aggregate 扩展的解决方案。

注意,下面不检查,也不关心是否得到一个锯齿状的子列表,它使用所有子列表的最大大小并根据当前列表填充。如果这是一个问题,可以向if 添加检查以检查所有子列表中的相同计数。

public static T[,] To2DArray<T>(this List<List<T>> lst)
{

    if ((lst == null) || (lst.Any (subList => subList.Any() == false)))
        throw new ArgumentException("Input list is not properly formatted with valid data");

    int index = 0;
    int subindex;

    return 

       lst.Aggregate(new T[lst.Count(), lst.Max (sub => sub.Count())],
                     (array, subList) => 
                        { 
                           subindex = 0;
                           subList.ForEach(itm => array[index, subindex++] = itm);
                           ++index;
                           return array;
                         } );
}

测试/使用

var lst = new List<List<string>>() { new List<string>() { "Alpha", "Beta", "Gamma" },
                                     new List<string>() { "One", "Two", "Three" },
                                     new List<string>() { "A" }
                                 };
var newArray = lst.To2DArray();

结果:

【讨论】:

    【解决方案4】:

    坦率地说,答案是否定的,不容易。

    也许您想编辑您的问题,为我们提供更多关于为什么需要这些声明的背景信息,我们可以帮助您解决根本问题?


    您的更新:

    我假设您无法更改需要将其传递到的函数。

    我不明白为什么您不能只使用object[,] 开头。这是我的建议。

    我怀疑这会对您的情况有所帮助,但它可能会使某些阵列在您开始时更容易工作。你知道List 上的.ToArray() 方法吗?

    【讨论】:

    • 是的,我知道这种方法,但我唯一一次使用它是当我得到一个单维数组时,是的,我无法使用 Object[,] 更改函数...有没有办法我可以声明一个object[,]而不指定大小,因为我不知道行数...
    • 我能给你的最好的参考是authors.aspalliance.com/remas/ASP.NET/VFAQNET/DynamicArrays 不过你肯定需要一个创造性的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 2019-07-09
    • 2011-08-24
    • 2019-04-03
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    相关资源
    最近更新 更多