1

today I just tried out the LINQ-Framework and wondered if there is a way doing the following. I have a list of adresses which contain a streetname and a housenumber. First I list all adresses based on thier streetnames by

list = list.OrderBy(x => x.StreetName)

If the streetnames are equal I want to compare the housenumbers as well using the ThenBy-expression, but here is the problem as the housenumber may consist of two parts: an integer (e.g. 12) and a string-suffix (e.g. A) which results in 12A. So I want to sort the list on the housenumber (the int value) and afterwards the suffix (the string value) as well. I also created the regex to split housenumber into int- and string value, so that´s not the problem, here is it: (\d+) *(\S)* but I come not across to get these two values (in some cases there´s only one as there is no suffix) to the sorting of LINQ as well.

I there any way of doing this?

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • Sorting by a whole string which is a number followed by a letter will yield exactly the same results as sorting by the number first and then the letter. – Ant P Nov 19 '13 at 08:58
  • Maybe it's easier to write a small custom comparer for the house number, than messing around like that. But, nevertheless, comparing strings as @AntP mentions is actually what you need. – Andrei V Nov 19 '13 at 08:59
  • @AntP if sort as string - `"15"`>`"123"` – Grundy Nov 19 '13 at 09:00
  • @Grundy D'oh - very true. – Ant P Nov 19 '13 at 09:00
  • Why are you splitting the two things up in the first place? Not every house *has* a house number. Some just have names. This is why pretty much every website/system has a "First line of address". Assuming there is a number and a possible suffix is creating more work than you need. – Moo-Juice Nov 19 '13 at 09:00
  • In my application we can expect that a house as such a housenumber: `int [+any number of whitespaces][+string]` – MakePeaceGreatAgain Nov 19 '13 at 09:09

2 Answers2

7

A better approach is to make your class implement the IComparable interface. Then you can call a Sort and youre done.

// something like this
class Address  : IComparable<Address>
{
    public int Housenumber { get; set; }
    public string HousenumberExtra { get; set; }

    public int CompareTo(Address other)
    {
        var compareResult = Housenumber.CompareTo(other.Housenumber);

        if (compareResult == 0)
            return HousenumberExtra.CompareTo(other.HousenumberExtra);

        return compareResult;
    }
}

If you really want to use linq you could do this (multiple ThenBy)

var result = addresses
    .OrderBy(i => i.Streetname)
    .ThenBy(h => h.Housenumber)
    .ThenBy(he=> he.HousenumberExtra);
lordkain
  • 3,061
  • 1
  • 13
  • 18
  • 3
    This answer would benefit from examples. – Ant P Nov 19 '13 at 09:02
  • I also played with this idea, I fear this is the way I do – MakePeaceGreatAgain Nov 19 '13 at 09:07
  • 1
    @HimBromBeere no fear :) you can use windows's own [Natual sort](http://stackoverflow.com/questions/248603/natural-sort-order-in-c-sharp) to compare the string – Jens Kloster Nov 19 '13 at 09:09
  • No, the actual reason I fear this is because I have to derive from the class which I want to sort because I´m not allowed to change this base class... but then putting derived types to the list is bit complicated... however this is another problem. Btw.: this is actual the way I currently use... – MakePeaceGreatAgain Nov 19 '13 at 09:12
  • 1
    can, or is, the class partial? – lordkain Nov 19 '13 at 09:13
  • The problem on your Edit is, that number and suffix are defined in one single string, there is no devided number- and suffix-definition so I cannot access them by another ThenBy:( – MakePeaceGreatAgain Nov 19 '13 at 09:28
0

My current approach looks like the following, which is OK for my needs but maybe not best:

buildings.Sort(delegate(Adress g1, Adress g2)
{
    int compare = String.Compare(g1.StreetName, g2.StreetName);
    if (compare == 1 || compare == -1) return compare;

    else {
        // ...
        // split the housenumber into int and string part using a regex
        // ...
        if h1 < h2 return -1;  // h1 and h2 are the numbers
        else if h1 > h2 return 1;
        else return String.Compare(suffix1, suffix2); 

    };
});

Hoped for a solution with LINQ as this may be bit shorter, but obviously there is none...

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111