如何将list<>转换为多维数组?

5

我有以下方法签名:

public void MyFunction(Object[,] obj)

我创建了这个对象:

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

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


更新:

事实上,我喜欢使用List,因为我可以轻松地添加新项。 有没有一种方法可以声明我的List<>对象以适应此需求? 我知道我的Object[,]中的列数,但不知道行数。


1
使用锯齿数组(T [] [])是一个选项吗?因为它可以使代码更容易(您可以在内部级别使用List <T> .ToArray())。 - mmmmmmmm
4个回答

11

实际上,它们并不一定是兼容的数组。

[,] 定义了一个多维数组。 List<List<T>> 更符合锯齿形数组(object[][])的定义。

问题在于,对于您原始的对象,列表中包含的每个 List<object> 可能具有不同数量的对象。 您需要创建一个内部列表最大长度的多维数组,并使用 null 值进行填充或类似方法来匹配它


看起来你的一些文本被吃掉了。你应该使用<和>代替文字角括号。 - sblom
然而,即使嵌套列表中的源数据永远无法“不规则”,仍有充分的理由希望这样做。原因是T[,]没有实现IEnumerable<T>,但T[][]有...请参见此问题:https://dev59.com/GXE85IYBdhLWcg3w43wX - rohancragg

7
你不可能得到一个非常简单的解决方案(例如几行代码)。在这种情况下,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元素包含的每个List<T>具有相同的长度。(否则,您真的需要使用锯齿状数组。)


我已经得到了类似于你的东西,但我希望有一种更快的方法来完成它。无论如何,谢谢你,你的解决方案更加通用! - Melursus
1
顺便说一句,对于不规则数组来说非常容易:objects.Select(subObjects => subObjects.ToArray()).ToArray(); - Samuel
@Samuel:是的,那正是我想建议的。 - Noldorin
@Noldorin 为了编译,您可能希望建议读者将其声明为:public static T [,] To2dArray <T>(this List <List <T>> list)在[public static class Extension]内。 - rohancragg
'j' 循环应该是:for (int j = 0; j < list[i].Count; j++) - Steven P
显示剩余2条评论

2

以下是使用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();

结果:

这里输入图片描述


(注:该内容为HTML代码,已经翻译为中文,不需要再次翻译)

-2
坦白地说,答案是否定的,不容易实现。
也许您想编辑您的问题,向我们提供更多关于为什么需要这些声明的背景信息,我们可以帮助您解决根本问题?

关于您的更新:

我猜想您无法更改需要传递此参数的函数。

我不明白为什么您不能一开始就使用一个 object[,]。这是我的建议。

我怀疑这对您的情况没有帮助,但它可能会使您开始处理数组时更容易。您知道关于 List.ToArray() 方法吗?


是的,我知道这个方法,但它只适用于单维数组,而且我不能改变使用Object[,]的函数...有没有办法声明一个对象[,]而不指定大小,因为我不知道行数... - Melursus
1
我能给你的最好参考是http://authors.aspalliance.com/remas/ASP.NET/VFAQNET/DynamicArrays/不过你肯定需要一个创造性的解决方案。 - GEOCHET

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接