tags:

views:

97

answers:

4

Hi

I have a list of dates for an event in the following format

13/04/2010 10:30:00
13/04/2010 13:30:00
14/04/2010 10:30:00
14/04/2010 13:30:00
15/04/2010 10:30:00
15/04/2010 13:30:00
16/04/2010 10:30:00
17/04/2010 11:00:00
17/04/2010 13:30:00
17/04/2010 15:30:00

How can i have the list be output, so that the date is only displayed once followed by the times for that date, so the above list would look like something like this:

13/04/2010 
10:30:00
13:30:00

14/04/2010 
10:30:00
13:30:00

15/04/2010 
10:30:00
13:30:00

16/04/2010 
10:30:00

17/04/2010 
11:00:00
13:30:00
15:30:00
+11  A: 

Well I don't know about the display side, but the grouping side is easy if you're using .NET 3.5+:

var groups = list.GroupBy(dateTime => dateTime.Date);

foreach (var group in groups)
{
    Console.WriteLine("{0}:", group.Key);
    foreach(var dateTime in group)
    {
        Console.WriteLine("  {0}", dateTime.TimeOfDay);
    }
}
Jon Skeet
You could also convert this into a single IEnumerable<string> if you wanted - just replace each Console.WriteLine() with a yield return. Then it's easy enough to send that to the console, but you can also bind to a data control or do anything else you want.
Joel Coehoorn
This is your answer. You are crazy fast Jon!
Audie
DateTime + C# == JonSkeet signal.
Joel Coehoorn
kb
A: 
        List<DateTime> dateTimes = new List<DateTime>();
        Dictionary<string, List<string>> data = new Dictionary<string, List<string>>();
        foreach (DateTime t in dateTimes)
        {
            if (!data.ContainsKey(t.ToShortDateString()))
            {
                data.Add(t.ToShortDateString(), new List<string>());
            }

            data[t.ToShortDateString()].Add(t.ToShortTimeString());
        }

        foreach (string key in data.Keys)
            data[key].Sort();

        foreach (var pair in data)
        {
            Console.WriteLine(pair.Key);
            foreach (string time in pair.Value)
                Console.WriteLine(time);

            Console.WriteLine();
        }
Greg B
Why all the string conversions? Why not just convert at the point of display?
Jon Skeet
A: 

If you have your dates in something like a List<DateTime> then you could do this:

DateTime dtTemp = DateTime.MinValue;
StringBuilder sb = new StringBuilder();
foreach(DateTime dt in MyDateList)
{
    if (dt == dtTemp) sb.AppendLine(dt.ToString("HH:mm:ss"));
    else
    {
        dtTemp = dt;
        sb.AppendLine();
        sb.AppendLine(dt.ToString("dd/MM/yyyy HH:mm:ss"));
    }
}
Console.WriteLine(sb.ToString().Trim());

Edit: Trim output to eliminate blank first line.

JYelton
That would only work if the dates are already grouped in the input, which was true in the example, but not stated. Just mentioning it, if the OP's example was not what he wanted. And you will be writing an extra line at the beginning.
Martinho Fernandes
You're right, I assumed the list was sorted based on the example. Thanks.
JYelton
A: 

Here's everything in one big LINQ query:

var output = dates.GroupBy(dt => dt.Date)
                  .Aggregate(new StringBuilder(),
                             (sb, g) => sb.AppendLine(g.Key.ToString("dd/MM/yyy"))
                                          .AppendLine(g.Select(dt => dt.ToString("HH:mm:ss"))
                                                       .Aggregate(sb,
                                                                  (sb_,dt) => sb_.AppendLine(dt),
                                                                  sb_ => sb_.ToString()),
                             sb => sb.ToString());

(I'm not advocating writing code like this.)

Martinho Fernandes