Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

For logging purposes, I need to output a double[,] to the log file. So I need to represent the array as a string.

The following code gets the job done using basic C# 1 features, but I was wondering if there is a more elegant solution using Linq:

private static string OneRowPerLine(double[,] numbers)
{
    var ret = new StringBuilder();
    for(var i=numbers.GetLowerBound(0);i<=numbers.GetUpperBound(0);i++)
    {
        for (var j = numbers.GetLowerBound(1); j <= numbers.GetUpperBound(1); j++)
        {
            if(j>numbers.GetLowerBound(1))
            {
                ret.Append(",");
            }
            ret.Append(numbers[i, j]);
        }
        ret.Append(Environment.NewLine);
    }
    return ret.ToString();
}
share|improve this question
up vote 5 down vote accepted

First off, I think there may be bugs in your code. Specifically in the dimension parameters of some of the GetLowerBound() parameters. Based on a quick glance, it should be:

private static string OneRowPerLine(double[,] numbers)
{
    var ret = new StringBuilder();
    for(var i=numbers.GetLowerBound(0);i<=numbers.GetUpperBound(0);i++)
    {
        for (var j = numbers.GetLowerBound(1); j <= numbers.GetUpperBound(1); j++)
        {
            if(j>numbers.GetLowerBound(1))
            {
                ret.Append(",");
            }
            ret.Append(numbers[i, j]);
        }
        ret.Append(Environment.NewLine);
    }
    return ret.ToString();
}

I'll update this answer in a moment with some enhancements, but wanted to get this bit out of the way.

EDIT: here's a pair of methods which will do it a little more generically and without LINQ. It does employ generics (<T>) and extension methods (this), one of which is an iterator (yield return):

    private static string OneRowPerLine<T>(this T[,] numbers)
    {
        return string.Join(Environment.NewLine, numbers.FormatOneRow());
    }

    private static IEnumerable<string> FormatOneRow<T>(this T[,] numbers)
    {
        for (var i = numbers.GetLowerBound(0); i <= numbers.GetUpperBound(0); i++)
        {
            var row = new T[numbers.GetLength(1)];

            for (var j = numbers.GetLowerBound(1); j <= numbers.GetUpperBound(1); j++)
            {
                row[j] = numbers[i, j];
            }

            yield return string.Join(",", row);
        }
    }

call like this:

    double[,] stuff = {{1,2}, {3,4}, {5,6}};
    Console.WriteLine(stuff.OneRowPerLine());
share|improve this answer
    
Sure, these are bugs. Thanks! – Arne Lund Aug 29 '12 at 20:39
    
I have fixed the bugs in my code. – Arne Lund Aug 29 '12 at 20:47
    
It works for me. – Arne Lund Aug 30 '12 at 17:58

"Better"? I don't know. There is a different way to deal with this in LINQ. You can use Cast<T> to flatten an IEnumerable and the use Aggregate to generate a single string from all the elements in the enumerable. You can then "group" items by line depending on how far you are in the array. If you have a double[,], you might do something like this:

var text = numbers.Cast<double>()
    .Aggregate(string.Empty, (s, i) =>
                                {
                                if ((temp%(numbers.GetUpperBound(1) + 1)) == 0)
                                {
                                    s = s + Environment.NewLine;
                                }
                                temp++;
                                return s + i.ToString(CultureInfo.InvariantCulture) + ", ";
                                });

If you like StringBuilder better:

var text = numbers.Cast<double>()
    .Aggregate(new StringBuilder, (s, i) =>
                                {
                                if ((temp%(numbers.GetUpperBound(1) + 1)) == 0)
                                {
                                    s.Append(Environment.NewLine);
                                }
                                temp++;
                                return s.Append( i.ToString(CultureInfo.InvariantCulture)).Append(", ");
                                }).ToString();
share|improve this answer
2  
I think the math here makes is non-obvious what the code actually does and whether it's correct. – svick Aug 30 '12 at 6:50
    
Can you use a StringBuilder instead of a string in you solution? – Arne Lund Aug 30 '12 at 13:10
    
@svick Hence my comment about "different" – Peter Ritchie Aug 30 '12 at 14:52
    
+1 This is interesting. Thanks! – Arne Lund Aug 30 '12 at 17:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.