• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 326
  • Last Modified:

Sorting alphanumeric table column correctly

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
MyersA
Asked:
MyersA
  • 4
  • 4
1 Solution
 
JarodtweissCommented:
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
 
MyersAAuthor Commented:
Yes, that's how I want to sort them.
0
 
MyersAAuthor Commented:
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
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
praneethaCommented:
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
 
MyersAAuthor Commented:
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
 
JarodtweissCommented:
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
 
JarodtweissCommented:
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
 
MyersAAuthor Commented:
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
 
JarodtweissCommented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now