3
\$\begingroup\$

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();
}
asked Aug 29, 2012 at 20:05
\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

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());
answered Aug 29, 2012 at 20:19
\$\endgroup\$
2
  • \$\begingroup\$ I have fixed the bugs in my code. \$\endgroup\$ Commented Aug 29, 2012 at 20:47
  • \$\begingroup\$ It works for me. \$\endgroup\$ Commented Aug 30, 2012 at 17:58
2
\$\begingroup\$

"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();
answered Aug 29, 2012 at 21:16
\$\endgroup\$
3
  • 2
    \$\begingroup\$ I think the math here makes is non-obvious what the code actually does and whether it's correct. \$\endgroup\$ Commented Aug 30, 2012 at 6:50
  • \$\begingroup\$ Can you use a StringBuilder instead of a string in you solution? \$\endgroup\$ Commented Aug 30, 2012 at 13:10
  • \$\begingroup\$ @svick Hence my comment about "different" \$\endgroup\$ Commented Aug 30, 2012 at 14:52

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.