tags:

views:

108

answers:

8

Hey there, I have this foreach loop that doesnt work 100%. Basically I am outputting a string. My problem is I dont want sb.Append(","); to be added the last record in the loop. IS there an easy way using linq to solve this?

 sb.Append("Readings:[");
                    foreach (var reading in lake.Reading)
                    {
                        sb.Append("[");
                        sb.Append("\"");
                        sb.Append(reading.DateTime.ToString("dd-MMM-yy"));
                        sb.Append("\"");
                        sb.Append(",");
                        sb.Append(reading.Level);
                        sb.Append("]");
                //only insert this line if its the not the last record        sb.Append(",");
                    }
                sb.Append("]");
A: 

You can use normal for loop like

for(int i=0;i< lake.Reading.count;i++)

zish
He asked for a LINQ expression
Novitzky
A: 

create an array to lake.Reading with the ToArray() method and change the foreach into a for. The simply test your index against the count of elements in the array.

sb.Append("Readings:[");
Array list = late.Reading.ToArray();
                for (int i=0;i<list.Length;i++)
                {
                    var reading = list[i];
                    sb.Append("[");
                    sb.Append("\"");
                    sb.Append(reading.DateTime.ToString("dd-MMM-yy"));
                    sb.Append("\"");
                    sb.Append(",");
                    sb.Append(reading.Level);
                    sb.Append("]");
                    if (i!=list.Length-1)
                       sb.Append(",");
                }
            sb.Append("]");
Tudor Carean
+1  A: 

Not a Linq approach, but you could do this:

sb.Append("Readings:[");

bool isFirst = true;
foreach (var reading in lake.Reading)
{
    if( isFirst == false )
    {
        sb.Append( "," );
    }
    isFirst = false;

    sb.Append("[");
    sb.Append("\"");
    sb.Append(reading.DateTime.ToString("dd-MMM-yy"));
    sb.Append("\"");
    sb.Append(",");
    sb.Append(reading.Level);
    sb.Append("]");
}
sb.Append("]");

Even with Linq you would need to check if you are either on the first item or on the last.

Viper
+5  A: 

You should look into using String.Join() or String.Concat(). It makes making (comma-separated) lists as strings that much easier. And works nicely with LINQ.

var combine = from r in lake.Reading
              select String.Format("[\"{0:dd-MMM-yy}\",{1}]", r.DateTime, r.Level);
var str = String.Format("Readings:[{0}]", String.Join(",", combine));
Jeff M
A: 

If you want to be concise, you could in fact use linq. But event if it is a solution, it's maybe not the best. Something like that should work:

lake.Reading.Aggregate(new StringBuilder(),
  (acc, value) => { return acc.AppendFormat("[{0},{1}],",value.Reading,value.Level); },
   acc => acc.Length > 1 ? (acc.Remove(acc.Length-1, 1).ToString()):string.Empty
  );

But string.Join would do the trick better I Think

Maupertuis
A: 

I have solved this three ways.

  • Trim the unwanted stuff after the loop.

  • Use a "started" bool, e.g.,

    // Warning -- Air code fragment
    bool started = false;
    foreach (...) {
       if (!started)
          started = true;
       else
          sb.Append(",");
       // Rest of the loop
    }
  • Created a wrapper for StringBuilder that does the "started" trick.
Mark Jerde
A: 

I usually use something like:

string s = lake.Reading
    .Select(r => "[\"" + r.DateTime.ToString("dd-MMM-yy") + "\"," + r.Level + "]")
    .Aggregate((n, m) => n + "," + m);
Thomas
A: 

It's not really LINQ that does the particular thing you ask for, but string.Join :

var formattedReadings = 
    from reading in lake.Reading
    select string.Format("[\"{0}\",{1}]", 
        reading.DateTime.ToString("dd-MMM-yy"), 
        reading.Level);

sb.Append("Readings:[");
sb.Append(string.Join(",", formattedReadings));
sb.Append("]");
AakashM