4

I am trying to convert an object[,] array (with for example some integers in it) to a string[,] array. I wrote this piece of code but Visual Studio gives me an error saying:

Cannot implicitly convert String[] to String[,].

What argument should I give to the Array.ConvertAll function? Thanks a lot.

object[,] input = GetSelectedRange();

string[,] dst = Array.ConvertAll<object[,], string[,]>(
    input, 
    x => x.ToString()
);
2
  • @keyboardP but the OP has ToString... Commented Feb 27, 2016 at 17:45
  • Yep tried the copy method but get an error because my input contains strings. Commented Feb 27, 2016 at 17:46

3 Answers 3

4

It would have been a lot easier if your item is object[][] rather than object[,]. But for object[,], why not using traditional method?

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

Suggestion by Olivier: to check if your input is null by using C#6 syntax ?.

Or, if you use lower version, use ternary operator:

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();
Sign up to request clarification or add additional context in comments.

12 Comments

Starting with C# 6.0: output[i, j] = input[i, j]?.ToString(); makes it a little bit safer. (Note the ?.)
@OlivierJacot-Descombes ah, C# 6! Why not? ;)
@OlivierJacot-Descombes updated to check if the input is null
Have you used <= instead of <? Debug!
Yep it's an Excel range, adapted the code and it works now. @Ian: Thanks a lot my friend!
|
3

Array.ConvertAll() only handles one-dimensional arrays. The input is expected to be an array of the input type and produces an array of the output type. The converter is expecting something that can convert object[,] -> string[,].

Multi-dimensional arrays do not have generic convert method, you would have to do it by hand. You could do something like this:

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;
}

Then you could do this to do the conversion:

var input = GetSelectedRange();
var converted = ConvertAll(input, x => x.ToString());

If it's possible that the source array is not 0-based, some adjustments would need to be made to handle the changed bounds.

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;
}

For a general purpose converter that can handle all arrays, this could be used.

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);
    }
}

You'll just need to cast back the array to the expected type (since the rank could not be expressed).

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

If you wanted some strong typing, you could create the appropriate overloads for the types you want to support.

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[,,];

Comments

0

From: https://stackoverflow.com/a/5083690/380384

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);

Note that this not converting but re-casting. It works if the object elements are really string elements (like what comes from a Excel worksheet).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.