Solved

Sorting alphanumeric table column correctly

Posted on 2004-09-24
12
283 Views
Last Modified: 2012-06-27
How can I sort a table column correctly when the table has values like "0", "A1", "AA-1", "B21", "3C", 4-32A", "1", "11-1", 2-A", etc...

Windows Explorer (in XP) seems to do this correctly when I sort files with these names.  In the column, I tried padding all values with 0's and the sorting improved but it still wasn't correct.

Basically, I want to emulate the Windows XP file sorting.
Any help is appreciated.

Thanks.
0
Comment
Question by:MyersA
  • 4
  • 4
12 Comments
 
LVL 4

Expert Comment

by:Jarodtweiss
ID: 12147755
How do you want to sort this ?
For me Windows XP sort me the file like this :
0.txt
1.txt
11-1.txt
2-A.txt
3C.txt
4-32A.txt
A1.txt
AA-1.txt
B21.txt

If you want to sort in another way, I'm using a custom type that implements the IComparable interface.
Can you explain better the sort you want to implement ?
0
 
LVL 2

Author Comment

by:MyersA
ID: 12147774
Yes, that's how I want to sort them.
0
 
LVL 2

Author Comment

by:MyersA
ID: 12147814
Sorry. In my XP Windows Explorer, this is how the sort looks like (the files don't have extensions):

0
1
2-A
3C
4-32A
11-1
A1
AA-1
B1
B21
BB1

Maybe the extensions produce a different order. But I want it sorted like above.
0
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
LVL 15

Expert Comment

by:praneetha
ID: 12147968
string[] temp= this.TextBox2.Text.Split(',');//{"0.txt","1.txt","11-1.txt","2-A.txt","3C.txt","4-32A.txt","A1.txt","AA-1.txt","B21.txt"};
                  Array.Sort(temp);
                  foreach(string s in temp)
                  {
                              this.TextBox1.Text+=s+"*";
                  }


and i enter in textbox2=0.txt,A1.txt,AA-1.txt,B21.txt,1.txt,11-1.txt,2-A.txt,3C.txt,4-32A.txt

and textbox1.text=0.txt*1.txt*11-1.txt*2-A.txt*3C.txt*4-32A.txt*A1.txt*AA-1.txt*B21.txt*

this one sorts like jarodtweiss XP machine ...

0
 
LVL 2

Author Comment

by:MyersA
ID: 12148024
Thanks for the post.

But in my Windows XP 11-1.txt is greater that 2-A.txt . the order would be like this:
0
1
2-A
3C
4-32A
11-1
A1
AA-1
B1
B21
BB1
0
 
LVL 4

Expert Comment

by:Jarodtweiss
ID: 12153856
Hey MyersA !

Here is what I suggest. In such a case, I definitely think that the IComparable interface is the solution you are searching.
If I understand, if you find some figures before the "-", you want to sort on the numeric order. Otherwise, it is the alpahabetical order.

So Maybe that you can do something like that in the CompareTo method:
1. Extract the first caharacter of the string that are numbers.
2. If A has some numbers and B doesn't, then return a negative number (A is before B)
3. If B has some numers and A doesn't then return a positive number
4. If A and B has some numbers return Anumbers.CompareTo(Bnumbers)
4. If A and B doesn't have numbers return A.CompareTo(B)

And this should work !
0
 
LVL 4

Expert Comment

by:Jarodtweiss
ID: 12153916
For extra info, here is what I have done :
(tested in VS.NET 2005, remove the generics so it can be used in previous version)
Note that the IComparable is not correctly written (coule be simplified, no exception if not correct type, ...)
But In the end, I have the correct sort order

    public class XpFileName : IComparable
    {
        string name;

        public XpFileName(string myName)
        {
            name = myName;
        }

        public string Name
        {
            get {return name;}
        }

        public int CompareTo(object myObj)
        {
            XpFileName myFile = (XpFileName)myObj;
            string myObjNumbers = string.Empty;
            string thisNumbers = string.Empty;
            for (int i = 0; i < myFile.name.Length; ++i)
            {
                if (char.IsDigit(myFile.Name[i]))
                    myObjNumbers += myFile.Name[i];
                else
                    break;
            }
            for (int i = 0; i < this.name.Length; ++i)
            {
                if (char.IsDigit(this.Name[i]))
                    thisNumbers += this.Name[i];
                else
                    break;
            }

            if (thisNumbers.Length > 0 && myObjNumbers.Length == 0)
                return this.name.CompareTo(myFile.name);
            if (thisNumbers.Length == 0 && myObjNumbers.Length > 0)
                return this.name.CompareTo(myFile.name);
            if (thisNumbers.Length == 0 && myObjNumbers.Length == 0)
                return this.name.CompareTo(myFile.name);
            if (thisNumbers.Length > 0 && myObjNumbers.Length > 0)
                return Convert.ToInt32(thisNumbers).CompareTo(Convert.ToInt32(myObjNumbers));

            return 0;
        }

        public override string ToString()
        {
            return this.Name;
        }

    }

            List<XpFileName> myList = new List<XpFileName>();
            myList.Add(new XpFileName("BB1"));
            myList.Add(new XpFileName("0"));
            myList.Add(new XpFileName("1"));
            myList.Add(new XpFileName("AA-1"));
            myList.Add(new XpFileName("4-32A"));
            myList.Add(new XpFileName("3C"));
            myList.Add(new XpFileName("B1"));
            myList.Add(new XpFileName("11-1"));
            myList.Add(new XpFileName("A1"));
            myList.Add(new XpFileName("B21"));
            myList.Add(new XpFileName("2-A"));
            Console.WriteLine("Before sort");
            for (int i = 0; i < myList.Count; ++i)
                Console.WriteLine(myList[i]);

            myList.Sort();
            Console.WriteLine("After sort");
            for (int i = 0; i < myList.Count; ++i)
                Console.WriteLine(myList[i]);
        }


0
 
LVL 2

Author Comment

by:MyersA
ID: 12161151
Thanks for the code.
Once I add this code, what do I need to do? All values that I add to the column go through the XpFilename constructor but function CompareTo is never called. I think I'm doing something wrong but I don't know what. Basically, I added a new class with your code and, in the Form. I do this:

DataRow dataRow = DataTableAddress.NewRow();
dataRow["prim_low"] = addr_rec.prim_low.TrimStart('0');  //column seen by user
dataRow["sorter"] = new ZM_Utilities.XpFilename(addr_rec.prim_low.TrimStart('0'));  //column to sort by. Value is full of leading zeroes.
DataTableAddress.Rows.Add(dataRow);

Thanks again.
0
 
LVL 4

Accepted Solution

by:
Jarodtweiss earned 75 total points
ID: 12167341
You do not have to call explicitely the CompareTo method, it is called automatically by the framework when you ask the sorting of a column.
In my example, it is done thru the myList.Sort
In your case, you should try :

DataTableAddress.DefaultView.Sort("sorter");
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Ivo
C# And Nullable Types Since 2.0 C# has Nullable(T) Generic Structure. The idea behind is to allow value type objects to have null values just like reference types have. This concerns scenarios where not all data sources have values (like a databa…
Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

860 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question