Sorting a list by DateTime stamp -- please help...

A

almurph

Hi,


I have a list object called "myList" with the first item a string and
the second a DateTime. Something like this:

"some text 1", 19/03/2008 12:56:36
"some text 2", 19/03/2008 10:56:36
"some text 3", 19/03/2008 11:56:36
"some text 4", 19/03/2008 13:56:36


I would like to sort "myList" (into a new list) by timestamp such
that the earliest time stamp is a tthe bottom. In this case it would
be:

"some text 2", 19/03/2008 10:56:36



Problem is though I don't know how to do this exactly! Would
appreciate any comments/suggestions/code-samples that you would liek
to share.

Thanking you,
Al.
 
J

Jon Skeet [C# MVP]

I have a list object called "myList" with the first item a string and
the second a DateTime. Something like this:

"some text 1", 19/03/2008 12:56:36
"some text 2", 19/03/2008 10:56:36
"some text 3", 19/03/2008 11:56:36
"some text 4", 19/03/2008 13:56:36

Do you mean you've got a list of lists, or a list of some type which
encapsulates a string and a DateTime?
I would like to sort "myList" (into a new list) by timestamp such
that the earliest time stamp is a tthe bottom. In this case it would
be:

"some text 2", 19/03/2008 10:56:36

Problem is though I don't know how to do this exactly! Would
appreciate any comments/suggestions/code-samples that you would liek
to share.

What version of .NET are you using? This is a lot easier in .NET 3.5...
 
A

almurph

Do you mean you've got a list of lists, or a list of some type which
encapsulates a string and a DateTime?




What version of .NET are you using? This is a lot easier in .NET 3.5...

Hi John,

Version 2.0
 
A

almurph

And the answer to the data type question?

Sorry John - didn't see the question - yes I have a class which
encapulated the data in a wrapper

public class aList
{
public string myString;
public DateTime updated;

public CacheList( string myString, DateTime updated)
{
this.myString = myString;
this.updated = updated;
}

}

Any suggestions?
 
J

Jon Skeet [C# MVP]

Sorry John - didn't see the question - yes I have a class which
encapulated the data in a wrapper

public class aList
{
public string myString;
public DateTime updated;

public CacheList( string myString, DateTime updated)
{
this.myString = myString;
this.updated = updated;
}

}

Any suggestions?

Sure. (For a start, I'd avoid public fields, but that's a different
matter.)

To sort a list in place, use:

list.Sort (delegate (CacheList first, CacheList second)
// Note ordering - this is to get earliest at bottom
{ return second.updated.CompareTo(first.updated); }
);

If you want to sort it as a *new* list, copy the list first:

List<CachedList> sorted = new List<CachedList>(list);
sorted.Sort (same code as above)
 
A

almurph

Sure. (For a start, I'd avoid public fields, but that's a different
matter.)

To sort a list in place, use:

list.Sort (delegate (CacheList first, CacheList second)
    // Note ordering - this is to get earliest at bottom
    { return second.updated.CompareTo(first.updated); }
);

If you want to sort it as a *new* list, copy the list first:

List<CachedList> sorted = new List<CachedList>(list);
sorted.Sort (same code as above)

--
Jon Skeet - <[email protected]>http://www.pobox.com/~skeet  Blog:http://www.msmvps.com/jon.skeet
World class .NET training in the UK:http://iterativetraining.co.uk- Hide quoted text -

- Show quoted text -

Thanks for that John - your a star. Concerning using public field -
can you explain? Any recommendations?

Interested,
Al.
 
J

Jon Skeet [C# MVP]

Thanks for that John - your a star.

No problem. Are you reasonably happy with the anonymous method syntax?

(Just for reference, using C# 3 and .NET 3.5 it really is trivial:

List<CachedList> sorted = list.OrderByDescending(item => item.updated)
.ToList();

:)
Concerning using public field -
can you explain? Any recommendations?

I'd suggest using properties to expose the data for "getters" - and
quite possibly make the type immutable at the same time. That has
various benefits, not least when it comes to multi-threading.

At some point I need to write up an article about why properties are
much better than public fields, and another about the benefits of
immutability (although the latter is documented in various places
perfectly well).
 
A

almurph

No problem. Are you reasonably happy with the anonymous method syntax?

Wish I knew what that meant!
(Just for reference, using C# 3 and .NET 3.5 it really is trivial:

List<CachedList> sorted = list.OrderByDescending(item => item.updated)
                              .ToList();

:)


I'd suggest using properties to expose the data for "getters" - and
quite possibly make the type immutable at the same time. That has
various benefits, not least when it comes to multi-threading.

You mean something like this:

public class aList
{
private string myString;
public MyString
{
get { return myString; }
}

private DateTime updated;
public Updated
{
get { return updated; }
}

public CacheList( string myString, DateTime updated)
{
this.myString = myString;
this.updated = updated;
}


}


Sorry - don't knwo how to make the type immutable! Help!
 
J

Jon Skeet [C# MVP]

Wish I knew what that meant!

The delegate (...) { ... } stuff.

See http://pobox.com/~skeet/csharp/csharp2/delegates.html
You mean something like this:

Yup, although with a name which matches the constructor :)
public class aList
{
private string myString;
public MyString
{
get { return myString; }
}

private DateTime updated;
public Updated
{
get { return updated; }
}

public CacheList( string myString, DateTime updated)
{
this.myString = myString;
this.updated = updated;
}
}


Sorry - don't knwo how to make the type immutable! Help!

You've already done it :)

You could make it "even more immutable" (which isn't quite as daft as
it sounds) by making the fields readonly - generally a good idea where
possible.
 
A

almurph

The delegate (...) { ... } stuff.

Sure. Had to change is slightly to make it work for your suggestions
but seems okay. Why is there a better way? Something I'm missing? Some
better way? Suggestions/comments appreciated Jon.
Seehttp://pobox.com/~skeet/csharp/csharp2/delegates.html



Yup, although with a name which matches the constructor :)

Done. thanks.
You've already done it :)

You could make it "even more immutable" (which isn't quite as daft as
it sounds) by making the fields readonly - generally a good idea where
possible.

Done. Thanks Jon
 
J

Jon Skeet [C# MVP]

Sure. Had to change is slightly to make it work for your suggestions
but seems okay. Why is there a better way? Something I'm missing? Some
better way? Suggestions/comments appreciated Jon.

If you're using C# 2, this is probably about as good as it gets IMO,
unless you use a custom comparer which applies a simpler predicate to
each element each time... that involves more work, but would make it
simpler to implement the next time you had to do something similar.

Unfortunately I don't have the time right now to explain myself more -
if no-one else has done it later, I'll do it myself :)
 
S

sloan

//
If you're using C# 2, this is probably about as good as it gets IMO,
unless you use a custom comparer which applies a simpler predicate to
each element each time... that involves more work, but would make it
simpler to implement the next time you had to do something similar.
//

(To the OP)
Follow the below link...read a little bit, and it'll show the Predicate and
simple comparer.


You would be very well served to read:
http://ludwig-stuyck.spaces.live.com/Blog/cns!E36D9BA98FC913B3!398.entry

the article on Generics.

It is in english.

...

Find the Sort section.




Sure. Had to change is slightly to make it work for your suggestions
but seems okay. Why is there a better way? Something I'm missing? Some
better way? Suggestions/comments appreciated Jon.

If you're using C# 2, this is probably about as good as it gets IMO,
unless you use a custom comparer which applies a simpler predicate to
each element each time... that involves more work, but would make it
simpler to implement the next time you had to do something similar.

Unfortunately I don't have the time right now to explain myself more -
if no-one else has done it later, I'll do it myself :)
 
J

Jon Skeet [C# MVP]

sloan said:
//
If you're using C# 2, this is probably about as good as it gets IMO,
unless you use a custom comparer which applies a simpler predicate to
each element each time... that involves more work, but would make it
simpler to implement the next time you had to do something similar.
//

(To the OP)
Follow the below link...read a little bit, and it'll show the Predicate and
simple comparer.

I followed the link but didn't find quite what I was expecting. I also
used the wrong word when I said predicate - I meant projection.

Basically, it's feasible to write an IComparer which you'd create
instances of like this:

IComparer<Person> comp =
ProjectionComparer.Create(Person p => p.Name);

Or something like that...

I'll see if I've got time to implement it later.
 
J

Jon Skeet [C# MVP]

Jon Skeet said:
If you're using C# 2, this is probably about as good as it gets IMO,
unless you use a custom comparer which applies a simpler predicate to
each element each time... that involves more work, but would make it
simpler to implement the next time you had to do something similar.

Unfortunately I don't have the time right now to explain myself more -
if no-one else has done it later, I'll do it myself :)

Okay, this is the kind of thing I meant. I've trimmed some of the XML
comments just because they ended up wrapping. The non-generic classes
are used to help with type inference. The only use for
MiscUtil.Extensions is for projection.ThrowIfNull - you can convert
that into
if (projection==null)
{
throw new ArgumentNullException("projection");
}

if you want.





using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MiscUtil.Extensions;
using System.Collections;

namespace MiscUtil.Collections
{
/// <summary>
/// Non-generic class to produce instances of the generic class,
/// optionally using type inference.
/// </summary>
public static class ProjectionComparer
{
public static ProjectionComparer<TSource, TKey>
Create<TSource,TKey>(Func<TSource, TKey> projection)
{
return new ProjectionComparer<TSource, TKey>(projection);
}

public static ProjectionComparer<TSource, TKey>
Create<TSource,TKey>
(TSource ignored,
Func<TSource, TKey> projection)
{
return new ProjectionComparer<TSource, TKey>(projection);
}

}

/// <summary>
/// Class generic in the source only to produce instances of the
/// doubly generic class, optionally using type inference.
/// </summary>
public static class ProjectionComparer<TSource>
{

public static ProjectionComparer<TSource, TKey>
Create<TKey>(Func<TSource, TKey> projection)
{
return new ProjectionComparer<TSource, TKey>(projection);
}
}

public class ProjectionComparer<TSource,TKey> : IComparer<TSource>
{
readonly Func<TSource, TKey> projection;

public ProjectionComparer(Func<TSource, TKey> projection)
{
projection.ThrowIfNull("projection");
this.projection = projection;
}

public int Compare(TSource x, TSource y)
{
// Don't want to project from nullity
if (x==null && y==null)
{
return 0;
}
if (x==null)
{
return -1;
}
if (y==null)
{
return 1;
}
return Comparer<TKey>.Default.Compare(projection(x),
projection(y));
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top