将 object[,] 转换为 string[,]?

12
你如何将 object[,] 转换为 string[,] ?
Object[,] myObjects= // sth
string[,] myString = // ?!? Array.ConvertAll(myObjects, s => (string)s) // this doesn't work

欢迎提出任何建议。

编辑:当然,循环解决方案显然可以做到,但我设想了一种更优雅的解决方案,无论是在代码还是性能上。

编辑2:这个object [,]当然包含string(和数字,但现在这不重要)。


2
你是想转换成 string[,] 还是 string[]?你的问题不一致。 - Jon Skeet
@VictorMukherjee 一个多维数组。 - Jodrell
1
一些关于为什么多维数组不好的细节 https://dev59.com/IXVC5IYBdhLWcg3wfxQ8,我会考虑转换为 IList<IList<>> - Jodrell
2
多维数组不是集合,除了循环(或通过黑魔法转换)外,无法进行任何操作。如果 Object[,] 实际上包含字符串,为什么一开始不是 string[,] 呢? - Alex
1
请注意,每种LINQ查询/扩展方法(以及类似方法)只是执行原始for循环的一种优美方式。您可能根本不会获得任何性能提升。 - Teejay
显示剩余8条评论
4个回答

4
Object[,] myObjects = new Object[3, 2] { { 1, 2 }, { 3, 4 },
                                        { 5, 6 } };

string[,] myString = new string[3, 2];

for (int i = myObjects.GetLowerBound(0); i < myObjects.GetUpperBound(0); i++)
{
     for (int j = myObjects.GetLowerBound(1); j < myObjects.GetUpperBound(1); j++)
     {
          myString[i, j] = myObjects[i, j].ToString();
     }
}

foreach (var item in myString)
{
    Console.WriteLine("{0} - {1}", item.GetType(), item);
}

输出将会是:

System.String - 1
System.String - 2
System.String - 3
System.String - 4
System.String - 5
System.String - 6

1
如果数组的下限不是0,会怎样? - ta.speot.is
@Soner Gönül:感谢你的回复,但是我想要一个更加优雅且在代码和性能方面更出色的解决方案。当然,这个方案也可以。 - HeinrichStack
@HeinrichStack 我研究了多维数组的这种转换,但是我没有找到更好的方法来实现它。 - Soner Gönül
来自Array.CreateInstance文章的@ta.speot.is: 通常,.NET Framework类库和许多编程语言不处理非零下限。 - Johnbot
@Johnbot 我只是问了一个问题,“如果数组的下限不是0怎么办”。 - ta.speot.is

4
你可以像这样分配空间。
string[,] myString = new string[myObjects.GetLength(0),myObjects.GetLength(1)];

然后一些循环应该可以正常工作,就像这样:

for(int k=0;k < myObjects.GetLength(0);k++)
    for(int l=0;l < myObjects.GetLength(1);l++)
        myString[k,l] = myObjects[k,l].ToString();

1
@HeinrichStack,这很好,假设ToString提供了你所需的转换。对于许多没有重写ToString()的类来说,花括号中的类型名称并不是很有用。然而,你不能指望“有用”会自动为你定义,它是上下文相关的。 - Jodrell
你不需要实例化 myString - Jodrell
@Jodrell - 我也没有给myObjects分配值,我假设还有其他代码,这只是一个片段,但你说得对。 - Hogan
@Hogan 十分感谢,不过我更期待在代码和性能方面找到更加优雅的解决方案。这个方案当然也可以使用。 - HeinrichStack
1
如果数组的下限不是0,会怎样? - ta.speot.is
@ta.speot.is - 那就会稍微复杂一些——分配和循环需要考虑到它。 - Hogan

4

在其他答案的基础上,编写一个自己的ConvertAll方法处理2D数组非常容易:

public static TOutput[,] ConvertAll<TInput, TOutput>(TInput[,] array, Func<TInput, TOutput> converter)
{
    var result = new TOutput[array.GetLength(0), array.GetLength(1)];
    for (int i = 0; i < array.GetLength(0); ++i)
        for (int j = 0; j < array.GetLength(1); ++j)
            result[i, j] = converter(array[i, j]);

    return result;
}

仅仅因为.NET的作者没有考虑把这个方法包括进去,就没有完全放弃的必要。你自己编写这个方法是非常直接的。
(如果你希望的话,可以将它变成扩展方法。)
在评论后编辑:如果你真的想处理那些某一维度下限不为零的数组,方法如下:
public static TOutput[,] ConvertAll<TInput, TOutput>(TInput[,] array, Func<TInput, TOutput> converter)
{
    int xMin = array.GetLowerBound(0);
    int xLen = array.GetLength(0);
    int yMin = array.GetLowerBound(1);
    int yLen = array.GetLength(1);
    var result = (TOutput[,])Array.CreateInstance(typeof(TOutput), new[] { xLen, yLen, }, new[] { xMin, yMin, });
    for (int x = xMin; x < xMin + xLen; ++x)
        for (int y = yMin; y < yMin + yLen; ++y)
            result[x, y] = converter(array[x, y]);

    return result;
}

1
@ta.speot.is 我隐式地假定2D数组是用通常的C#语法创建的。当然,我知道也可以像这样创建数组:(object[,])Array.CreateInstance(typeof(object), new[] { 10, 20, }, new[] { -3, -7, });,但谁会那样做呢?这个问题标记了 C#,你知道的。我应该加入处理这种不太可能的情况的代码吗? - Jeppe Stig Nielsen
这个问题被标记为C#,你知道吗?(object[,])Array.CreateInstance(typeof(object), new[] { 10, 20, }, new[] { -3, -7, }); 这段代码是用哪种语言编写的? - ta.speot.is
@WiiMaxx 我只是在转发这个回答 - ta.speot.is
2
@ta.speot.is 好的,我已经包含了非零下限的情况。虽然我认为___任何___C#开发人员都不会使用它。 - Jeppe Stig Nielsen
@JeppeStigNielsen 谢谢。保留新数组的下限会得到额外加分。 - ta.speot.is
显示剩余4条评论

3
这应该是最简单和最快的方法之一,前提是src数组中的每个元素都可以转换为dst数组类型。
object[,] src = new object[,]
{
    {"foo", "bar"},
    {"spam", "eggs"},
};

string[,] dest = new string[src.GetLength(0), src.GetLength(1)];
Array.Copy(src, dest, src.Length);

@ta.speot.is:没错,所以可能的技巧是用 null 填充剩余部分,然后复制到那个区域。或者你有更好的想法吗? - HeinrichStack
@WiiMaxx:你用的是double类型吗? - HeinrichStack
@HeinrichStack,我刚把"eggs"改成了5 - WiiMaxx
在我看来,创建一个包含多种类型的对象数组(例如{"spam", 5, 1.0})并假装某些神奇的方法可以执行我们期望的所有转换是没有任何意义的;:)特别是考虑到有几种将数字转换为字符串的方法,这取决于CultureInfo - Paolo Moretti
@PaoloMoretti 我提到数字只是因为原帖中的2Edit _“(还有数字,但现在不重要)”_。所以不用担心,我对你的解决方案很满意。 - WiiMaxx
显示剩余8条评论

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