rulururu

post Sorting Strings containing Numbers

March 24th, 2008

Filed under: .NET, General Programming — Kai @ 6:20 pm

It’s often necessary to sort lists. The Sort method of ArrayList class shows that it can’t be difficult. Also some other classes can be sorted unless they are type IComparable.
The sort method of ArrayList class has several overloads, some can be given to a Comparer, which implements the IComparer interface.

The interface has just one method called Compare which returns equal, greater or smaller depending on the two values it compares.

If you’d make your own comparer you’d simply do that like this:

public class MySpecialComparer : object, System.Collections.IComparer
{
 
    /// <summary>
    /// Default constructor - initializes all fields to default values
    /// </summary>
    public MySpecialComparer()
    {
    }
}

There’s also a difference in ascending and descending sort order. Mention the following code which compares String descending:

public class DescendingComparer : IComparer
{
  public int Compare(object objA, object objB)
  {
    return String.Compare(objB.ToString(), objA.ToString());
  }
}

The trick is just to compare B to A and not the way round.

To sort a simplest one dimensional array in alphabetical order, we’ll leverage the static “Sort” method in the Array class to sort the array. The Array.Sort method will sort the array in place, meaning we don’t have to create another array to contain the resulting array. Here is how:

String[] myAnimals = {"Zebra","Elephant","Snake"};
Array.Sort(myAnimals);

As expected this will result in the array getting sorted in the ascending order i.e. iterating the elements of this array will cause the output in the following manner:

Elephant, Snake, Zebra

Computer string sorting algorithms generally don’t order strings containing numbers in the same way that a human would do. Consider:

rfc1.txt, rfc2086.txt, rfc822.txt

It would be more friendly if the program listed the files as

rfc1.txt, rfc822.txt, rfc2086.txt

Filenames sort properly if people insert leading zeros, but they don’t always do that.
It’s kinda tricky when strings that contain numbers are sorted ’cause they’ve to be sorted numerically.

Imagine an array of values like this:

string[] Items = { "z4", "z2", "z15", "z1" };

The idea is to write a Comparer (implements IComparer) which extracts the numeric part e.g. by RegEx: [0-9]*
Then sort as already familiar with a Collections.Sort method that uses the comparator.

Generally you’d “invent” an algorithm that breaks strings into chunks, where a chunk contains either all alphabetic characters, or all numeric characters. These chunks are then compared against each other. If both chunks contain numbers, a numerical comparison is used. If either chunk contains characters, the ASCII comparison is used.

Ian Griffith offered a code sample that helps to handle string sorting with numbers:

/// <summary>
/// Compares two sequences.
/// </summary>
/// <typeparam name="T">Type of item in the sequences.</typeparam>
/// <remarks>
/// Compares elements from the two input sequences in turn. If we
/// run out of list before finding unequal elements, then the shorter
/// list is deemed to be the lesser list.
/// </remarks>
public class EnumerableComparer<T> : IComparer<IEnumerable<T>>
{
    /// <summary>
    /// Create a sequence comparer using the default comparer for T.
    /// </summary>
    public EnumerableComparer()
    {
        comp = Comparer<T>.Default;
    }
 
    /// <summary>
    /// Create a sequence comparer, using the specified item comparer
    /// for T.
    /// </summary>
    /// <param name="comparer">Comparer for comparing each pair of
    /// items from the sequences.</param>
    public EnumerableComparer(IComparer<T> comparer)
    {
        comp = comparer;
    }
 
    /// <summary>
    /// Object used for comparing each element.
    /// </summary>
    private IComparer<T> comp;
 
 
    /// <summary>
    /// Compare two sequences of T.
    /// </summary>
    /// <param name="x">First sequence.</param>
    /// <param name="y">Second sequence.</param>
    public int Compare(IEnumerable<T> x, IEnumerable<T> y)
    {
        using (IEnumerator<T> leftIt = x.GetEnumerator())
        using (IEnumerator<T> rightIt = y.GetEnumerator())
        {
            while (true)
            {
                bool left = leftIt.MoveNext();
                bool right = rightIt.MoveNext();
 
                if (!(left || right)) return 0;
 
                if (!left) return -1;
                if (!right) return 1;
 
                int itemResult = comp.Compare(leftIt.Current, rightIt.Current);
                if (itemResult != 0) return itemResult;
            }
        }
    }
}

When using it a regular expression for the numbers is needed.
Using C# 3.0 it can be used that way:

Func<string, object> convert = str =>
{   try { return int.Parse(str); }
    catch { return str; } };
 
var sorted = testItems.OrderBy(
    str => Regex.Split(str.Replace(" ", ""), "([0-9]+)").Select(convert),
    new EnumerableComparer<object>());

Again the lambda expression can help a lot. sorted is an untyped listed that can be iterated with foreach.

When sorting / comparing strings that contain numbers you always should consider to sort them the way a human would do.

1 Comment »

  1. […] 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384325ci Symptoms, 2000 Bmw 325ci Sale - 270.tvshowzone.com325ci Symptoms, 2000 Bmw 325ci Sale325ix performance parts bmw 325ci replacement 330xi 2006 bmw 325ci brake 325 discount 325ci auto parts bmw 323i 2001 bmw 325ci oil bmw 325ci oxygen sensor 2004 bmw 325ci convertible 2004 bmw 325ci cars for sale 2006 bmw 325ci salvage bumper 325e parts bmw 325ci 325ix aftermarket 320i bmw 325ci replacement 2006 bmw 325ci cars 2005 325i gas mileage bmw 325ci 328i radiator drain plug parts bmw 325ci 325ci space 2004 bmw 325cic sport package 745li used z3 325ci bmw 528i 2001 325i oil light bmw 325ci 1988 bmw 325ci 530xi radiator hq bmw 325ci bmw 325ci bulb socket 2004 bmw 325ci upgrades bmw e46 330ci vs 325ci 325ci used car prices 6 cylinder 1998 323is coupe road test bmw 325ci 2003 bmw 3 series 325ci convertible review 330xi parts bmw 325ci 2003 bmw 325ci used 325is discount odm 2006 bmw 325ci bmw 325ci vancouver vehicles for sale buy 325 bmw 325ci fog light model 2004 bmw 325ci 325ci radiator support replacement honda bmw 325ci headlight bulbs 330i radiator fan expansion tank bmw 325ci 325ci aftermarket air intake 2002 bmw 325ci coupe specs bmw 325ci e46 car and driver bmw 325ci bulb headlight assembly 325e used oil pan bmw 325ci 325ci bulbapedia xenon hid 325ci replacement discount bmw parts 325ci headlight replacement factory exhaust 530i bmw 325ci bmw 325ci part oxygen sensor headlight xenon bmw 325ci 325ci network 325ci alternative 2003 bmw 2005 bmw 325ci options bulb 325ci bmw e46 330xi radiator shroud e46 bmw 325ci 325ci pirate bay 325 aftermarket cold air intake bmw 325ci k&n 57i 325ci convertible sale used bmw upgrade e46 325ci 2001 bmw 325ci edmunds 325ci discount 1995 bmw 325is bmw 325ci sport mpg aftermarket engine 325i bmw 325ci best tires bmw 325ci 330ci headlight assembly bmw 325ci bmw 325ci radiator home depot nissens 325i radiator bmw 325ci 325ci cal bmw 325ci pictures cooling system bmw 325ci recalls 328ci wholesale 328is bmw 325ci part discount 2002 bmw 325ci 325is part discount 325ci bmw 740i 2002 bmw 325ci turbo 2003 325i spec bmw 325ci 325ci oem bmw e46 325xi radiator behr 325ci bmw 323ci 2002 325ci parts bmw power steering pump bmw 325ci automobile body kit 330i 2005 bmw 325ci 850 for sale texas bmw 325ci 2001 bmw 325ci oxygen sensor download 325ci new bmw used car 323ci bmw 325ci 2003 325i headlight bulb 2001 bmw 325ci refurbished bmw series 325ci radiator cap bmw 325ci 850ci fan 01 bmw 325ci convertible 2004 525i used parts bmw 325ci 325ci heater crp 528i aftermarket headlights bmw 325ci e46 325ci reviews cheap 325is bmw 325ci bmw 325ci promotion brake pads dvd 325ci 850i parts new 850csi bmw 325ci 2005 bmw 325ci battery bmw 325ci se review 2002 bmw 325ci 2002 bmw 325ci edmunds 325ci accessories high quality 325ci buy australia 325ci 1991 bmw 325i buy 325ci 1988 bmw 325 540i sale autos m5 bmw 325ci Mercury Zephyr Discount | R63 Headlight Tail | Caliber Control Seiko | American Express Cars | Lightbulb 1992 Geo | […]

    Pingback by 325ci Symptoms, 2000 Bmw 325ci Sale - 270.tvshowzone.com — May 23, 2010 @ 12:47 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment

ruldrurd
Powered by WordPress, Content and Design by Kai Bellmann
Entries (RSS) and Comments (RSS)