How to naturally sort a DataView using something like IComparable

My DataView is fun and sorting things alphabetically, and I need this for numerical sorting. I searched this entire Internet and found a lot of ideas on how to sort it using ICompare, but nothing sensible.

So my questions

  1. How do I implement ICompare for a DataView (look for the code here).
  2. How to properly decrypt a column full of rows, which are the actual rows, and a column full of numbers (with commas).

I need code to help me with this guys. I was more or less lost in the idea of ​​ICompare and how to implement it in various scenarios, so it would be nice to give a good explanation.

Also, please do not give me links. I am looking for solid answers to this question.

Some kind of code I'm using.

DataView dataView = (DataView)Session["kingdomData"]; dataView.Sort = e.SortExpression + " " + ConvertSortDirectionToSql(e.SortDirection); gvAllData.DataSource = dataView; gvAllData.DataBind(); private string ConvertSortDirectionToSql(SortDirection sortDirection) { string newSortDirection = String.Empty; if (Session["SortDirection"] == null) { switch (sortDirection) { case SortDirection.Ascending: newSortDirection = "ASC"; break; case SortDirection.Descending: newSortDirection = "DESC"; break; } } else { newSortDirection = Session["SortDirection"].ToString(); switch (newSortDirection) { case "ASC": newSortDirection = "DESC"; break; case "DESC": newSortDirection = "ASC"; break; } } Session["SortDirection"] = newSortDirection; return newSortDirection; } 

For this scenario, I dynamically create a data table and put it in the data view, where I put the data view in the grid view, and also remember to put the data view in the session object for sorting capabilities.

When the user calls the grid view to sort the column, I recall the data view in the session object and build the sort expression of the data view as follows:

 dataview.sort = e.sortexpression + " " + e.Sortdirection; 

Or something like that. What usually happens is suitable for all real strings, such as

Car; Home; Cattle; Zack etc ...

But when I do the same for numeric fields with comma separated values, it turns out something like

900; 800; 700; 600; 200; 120; 1200; 12340; 1,000,000;

See what I'm talking about? It just sorts the elements as alpha sort instead of the natural one. I want my Dataview to NATURALLY sort numerical columns as follows:

120; 200; 600; 700; 800; 900; 1200; 12340; 1,000,000;

Let me know what you can do to help me.
Postscript I have looked through countless articles on how to do this, and they all talk about adding to a list / array and doing it this way, but is there a much more efficient way?

+4
source share
3 answers

In the first release, IIRC, you cannot sort a DataView with a comparator. If you just need to sort the number in the field, you need to be sure that the column type is numeric, not string. Some code will help figure this out.

In the second problem, you also cannot do this directly in the DataView. If you really need to sort the records based on some data processing in the column, then I would copy the data in the array and use IComparer in the array:

 DataView dv = new DataView(dt); ArrayList lst = new ArrayList(); lst.AddRange(dv.Table.Rows); lst.Sort(new MyComparer()); foreach (DataRow dr in lst) Debug.WriteLine(dr[0]); 

The comparison looks like this:

  class MyComparer : IComparer { public int Compare(object x, object y) { DataRow rx = x as DataRow; DataRow ry = y as DataRow; string datax = (string)rx[colName]; string datay = (string)ry[colName]; // Process datax and datay here then compare them (ASC) return datax.CompareTo(datay); } } 

This will increase memory consumption, so you need to consider if there is a better way to preprocess the data in the table so that you can sort the DataView data by column.

PS colName is the name of the column you are interested in. Replace the comment with actual code to extract the sorting information from the column. You can also use this method to extract sorting information from more columns. Just use something like this:

 int cmp = colAx.CompareTo(colAy); if (cmp != 0) return cmp; cmp = colBy.CompareTo(colBx); return cmp; 

This will be compared with an increase in colA values ​​and then a decrease in colB values ​​(not that the second comparison has y first, then x)

Edit : OK, I misinterpreted the term, separated by commas. From your example, I think that you actually meant numbers with thousands of delimiters (1,000,000 = one million). If you store such numbers in a database, it should be that you are using a text field, and this should be the reason that the sort order is alphanumeric.

Based on this assumption, I would suggest changing the type of this column to a numeric one, keeping normal numbers inside and formatting them (with thousands of separators) only when they are displayed. Thus, sorting should work directly in the DataView, and you do not need to copy the data.

+3
source

This is ugly, but:

  DataView dv = GetDataViewSomewhere(); //Naturally sort by COLUMN_TO_SORT_ON try { List<string> rowList = new List<string>(); foreach (DataRowView drv in dv) rowList.Add((string)drv["COLUMN_TO_SORT_ON"]); rowList.Sort(new NaturalComparer()); Dictionary<string, int> sortValueHash = new Dictionary<string, int>(); for (int i = 0; i < rowList.Count; i++) sortValueHash.Add(rowList[i], i); dv.Table.Columns.Add("NATURAL_SORT_ORDER", typeof(int)); foreach (DataRowView drv in dv) drv["NATURAL_SORT_ORDER"] = sortValueHash[(string)drv["COLUMN_TO_SORT_ON"]]; dv.Sort = "NATURAL_SORT_ORDER"; } catch (Exception) { DEBUG_TRACE("Could not naturally sort"); dv.Sort = "COLUMN_TO_SORT_ON"; } 

Where is NaturalComparer this class .

+1
source

For the script, I build dynamically dynamically and paste it into the dataview, where I put the dataview in the gridview, and also remember to put the dataview in the session object for sorting.

When the user calls gridview to sort the column, I remind the dataview in the session object and build the dataview sort expression as follows:

 dataview.sort = e.sortexpression + " " + e.Sortdirection; 

Or something like that. So what usually comes out is suitable for all real strings like

Car; Home; Cattle; zach etc.

But when I do the same for numbers of numbers With commas as separate values, it turns out something like

900; 800; 700; 600; 200; 120; 1200; 12340; 1,000,000;

See what I mean? It just sorts items as alpha sort instead of natural sort. I want my Dataview NATURALLY to sort the numeric columns correctly, like

120; 200; 600; 700; 800; 900; 1200; 12340; 1,000,000;

Let me know what you can do to help me.
Postscript I have looked through countless articles on how to do this, and they all say that they are inserted into a list / array and do it that way, but is there a more efficient way?

0
source

Source: https://habr.com/ru/post/1276845/


All Articles