将 Object[,] 转换为 String[,]

4

我正在尝试将一个object[,]数组 (例如其中有一些整数) 转换为string[,]数组。我编写了以下代码,但Visual Studio报错:

无法将String[]隐式转换为String[,]

请问我应该给Array.ConvertAll函数传递什么参数?非常感谢。

object[,] input = GetSelectedRange();

string[,] dst = Array.ConvertAll<object[,], string[,]>(
    input, 
    x => x.ToString()
);

@keyboardP 但是OP有 ToString... - Ian
尝试使用复制方法,但由于我的输入包含字符串,因此出现错误。 - André van der Heijden
3个回答

4

如果您的项是 object [][ ]而不是 object [,],那么事情将变得容易得多。但对于 object [,],为什么不使用传统的方法呢?

object[,] input = GetSelectedRange();
string[,] output = new string[input.GetLength(0), input.GetLength(1)];
for (int i = 0; i < input.GetLength(0); ++i)
    for (int j = 0; j < input.GetLength(1); ++j)
        output[i, j] = input[i, j]?.ToString(); //give additional ?. to check if your input is null

建议来自Olivier:使用C#6语法?.检查您的输入是否为空。

或者,如果您使用较低版本,请使用三元运算符:

object[,] input = GetSelectedRange();
string[,] output = new string[input.GetLength(0), input.GetLength(1)];
for (int i = 0; i < input.GetLength(0); ++i)
    for (int j = 0; j < input.GetLength(1); ++j)
        output[i, j] = input[i, j] == null ? null input[i, j].ToString();

@OlivierJacot-Descombes 啊,C# 6!为什么不呢?;) - Ian
1
@OlivierJacot-Descombes 更新以检查输入是否为空。 - Ian
1
你是否使用了<=而不是<?调试一下! - Olivier Jacot-Descombes
1
是的,它是一个Excel范围,我修改了代码,现在它可以工作了。@Ian:非常感谢你,我的朋友! - André van der Heijden
@AndrévanderHeijden 没问题!;) 很高兴你能解决你的问题! - Ian
显示剩余7条评论

3

Array.ConvertAll() 只能处理一维数组。输入应该是输入类型的数组,并生成输出类型的数组。转换器正在期望能够将 object[,] 转换为 string[,]

多维数组没有通用的转换方法,您需要手动完成。您可以像下面这样做:

public TOutput[,] ConvertAll<TInput, TOutput>(TInput[,] input, Func<TInput, TOutput> converter)
{
    var length0 = input.GetLength(0);
    var length1 = input.GetLength(1);
    var result = new TOutput[length0, length1];
    for (var i = 0; i < length0; ++i)
    for (var j = 0; j < length1; ++j)
        result[i, j] = converter(input[i, j]);
    return result;
}

然后您可以按照以下方式进行转换:
var input = GetSelectedRange();
var converted = ConvertAll(input, x => x.ToString());

如果源数组不是以0为基础的,那么需要进行一些调整来处理变化的边界。

public TOutput[,] ConvertAll<TInput, TOutput>(TInput[,] input, Func<TInput, TOutput> converter)
{
    var lengths = new[] { input.GetLength(0), input.GetLength(1) };
    var lowers = new[] { input.GetLowerBound(0), input.GetLowerBound(1) };
    var uppers = new[] { input.GetUpperBound(0), input.GetUpperBound(1) };
    var result = Array.CreateInstance(typeof(TOutput), lengths, lowers) as TOutput[,];
    for (int i = lowers[0], il = uppers[0]; i <= il; ++i)
    for (int j = lowers[1], jl = uppers[1]; j <= jl; ++j)
            result[i, j] = converter(input[i, j]);
    return result;
}

对于能够处理所有数组的通用转换器,可以使用以下方法。
public Array ConvertAll<TInput, TOutput>(Array input, Func<TInput, TOutput> converter)
{
    var rank = input.Rank;
    var lengths = Enumerable.Range(0, rank).Select(i => input.GetLength(i)).ToArray();
    var lowerBounds = Enumerable.Range(0, rank).Select(i => input.GetLowerBound(i)).ToArray();
    var upperBounds = Enumerable.Range(0, rank).Select(i => input.GetUpperBound(i));
    var output = Array.CreateInstance(typeof(TOutput), lengths, lowerBounds);
    ConvertRank(input, converter, output, new int[0], lowerBounds.Zip(upperBounds, Tuple.Create).ToArray());
    return output;
}

private void ConvertRank<TInput, TOutput>(Array input, Func<TInput, TOutput> converter, Array output, int[] indices, Tuple<int, int>[] bounds)
{
    if (!bounds.Any())
    {
        var value = input.GetValue(indices);
        var convertedValue = converter((TInput)value);
        output.SetValue(convertedValue, indices);
    }
    else
    {
        var start = bounds[0].Item1;
        var end = bounds[0].Item2;
        var tail = bounds.Skip(1).ToArray();
        for (var i = start; i <= end; i++)
            ConvertRank(input, converter, output, indices.Concat(new[] { i }).ToArray(), tail);
    }
}

您只需要将数组转换回预期的类型(因为无法表示秩)即可。

object[,,] input = GetSome3dObjectArray();
var converted = ConvertAll(input, (object x) => x.ToString()) as string[,,];

如果您需要一些强类型支持,您可以为您想要支持的类型创建适当的重载。

public TOutput[,] ConvertAll<TInput, TOutput>(TInput[,] input, Func<TInput, TOutput> converter) =>
    ConvertAll((Array)input, converter) as TOutput[,];
public TOutput[,,] ConvertAll<TInput, TOutput>(TInput[,,] input, Func<TInput, TOutput> converter) =>
    ConvertAll((Array)input, converter) as TOutput[,,];

0

来源:https://dev59.com/U2445IYBdhLWcg3wAFq0#5083690

object[,] src = new object[2, 3];

// Initialize src with test strings.
src[0, 0] = "aa";
src[0, 1] = "ab";
src[0, 2] = "ac";
src[1, 0] = "ba";
src[1, 1] = "bb";
src[1, 2] = "bc";

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

请注意,这不是转换而是重新分配类型。如果object元素确实是字符串元素(例如来自Excel工作表的内容),它就会起作用。

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