2017-01-10 2 views
0

Недавно я опубликовал вопрос и получил прекрасный ответ на натуральный вид datagrid здесь - Natural Sort for Datgridview. Затем я нашел подходящее решение для естественного сортирования списка, который затем был добавлен в поле со списком. Кажется, что существует много общего кода и задается вопросом, есть ли способ поделиться этим кодом. Я попытался, но один класс использует объекты и другие строки и попытался, как я мог бы не найти способ поделиться этим кодом. два класса, и как они назывались показано ниже: Для Datagrid:Поделиться ссылкой - Природный Сортировка сортировать по datagrid и списку

class NaturalSortComparer : System.Collections.IComparer 
    { 
     private System.Collections.Generic.Dictionary<string, string[]> table; 

     public NaturalSortComparer() 
     { 
      table = new System.Collections.Generic.Dictionary<string, string[]>(); 
     } 

     public void Dispose() 
     { 
      table.Clear(); 
      table = null; 
     } 

     public int Compare(object x, object y) 
     { 

       System.Windows.Forms.DataGridViewRow DataGridViewRow1 = (System.Windows.Forms.DataGridViewRow)x; 
       System.Windows.Forms.DataGridViewRow DataGridViewRow2 = (System.Windows.Forms.DataGridViewRow)y; 

       string xStr = DataGridViewRow1.Cells["Column1"].Value.ToString().ToLower(); 
       string yStr = DataGridViewRow2.Cells["Column1"].Value.ToString().ToLower(); 

      if (xStr == "") 
      { 
       return 0; 
      } 

      if (xStr == yStr) 
      { 
       return 0; 
      } 
      string[] x1, y1; 
      if (!table.TryGetValue(xStr, out x1)) 
      { 
       x1 = System.Text.RegularExpressions.Regex.Split(xStr.Replace(" ", ""), "([0-9]+)"); 
       table.Add(xStr, x1); 
      } 
      if (!table.TryGetValue(yStr, out y1)) 
      { 
       y1 = System.Text.RegularExpressions.Regex.Split(yStr.Replace(" ", ""), "([0-9]+)"); 
       table.Add(yStr, y1); 
      } 

      for (int i = 0; i < x1.Length && i < y1.Length; i++) 
      { 
       if (x1[i] != y1[i]) 
       { 
        return PartCompare(x1[i], y1[i]); 
       } 
      } 
      if (y1.Length > x1.Length) 
      { 
       return 1; 
      } 
      else if (x1.Length > y1.Length) 
      { 
       return -1; 
      } 
      else 
      { 
       return 0; 
      } 
     } 

     private static int PartCompare(string left, string right) 
     { 
      int x, y; 
      if (!int.TryParse(left, out x)) 
      { 
       return left.CompareTo(right); 
      } 

      if (!int.TryParse(right, out y)) 
      { 
       return left.CompareTo(right); 
      } 

      return x.CompareTo(y); 
     } 
    } 

и называлась:

dgvCategories.Sort(new NaturalSortComparer()); 

Для списков:

public class NaturalSortComparerList : IComparer<string>, IDisposable 
    { 

     #region IComparer<string> Members 

     public int Compare(string x, string y) 
     { 
      throw new NotImplementedException(); 
     } 

     #endregion 

     #region IComparer<string> Members 

     int IComparer<string>.Compare(string xwithcaps, string ywithcaps) 
     { 
      string x = xwithcaps.ToLower(); 
      string y = ywithcaps.ToLower(); 


      if (y == "") 
      { 
       return 0; 
      } 

      if (x == y) 
      { 
       return 0; 
      } 
      string[] x1, y1; 
      if (!table.TryGetValue(x, out x1)) 
      { 
       x1 = System.Text.RegularExpressions.Regex.Split(x.Replace(" ", ""), "([0-9]+)"); 
       table.Add(x, x1); 
      } 
      if (!table.TryGetValue(y, out y1)) 
      { 
       y1 = System.Text.RegularExpressions.Regex.Split(y.Replace(" ", ""), "([0-9]+)"); 
       table.Add(y, y1); 
      } 

      for (int i = 0; i < x1.Length && i < y1.Length; i++) 
      { 
       if (x1[i] != y1[i]) 
       { 
        return PartCompare(x1[i], y1[i]); 
       } 
      } 
      if (y1.Length > x1.Length) 
      { 
       return 1; 
      } 
      else if (x1.Length > y1.Length) 
      { 
       return -1; 
      } 
      else 
      { 
       return 0; 
      } 
     } 

     private static int PartCompare(string left, string right) 
     { 
      int x, y; 
      if (!int.TryParse(left, out x)) 
       return left.CompareTo(right); 

      if (!int.TryParse(right, out y)) 
       return left.CompareTo(right); 

      return x.CompareTo(y); 
     } 

     #endregion 

     private Dictionary<string, string[]> table = new Dictionary<string, string[]>(); 

     public void Dispose() 
     { 
      table.Clear(); 
      table = null; 
     } 
    } 

и называется

cats.Sort(new NaturalSortComparerList()); 

где кошки - это список, содержащий записи, содержащие буквы и цифры.

Вы заметите, что код в двух методах сравнения варьируется для обработки строки "". Мне нужно, чтобы это было в верхней части списка или datagrid. Для DataGrid в NaturalSortComparer мне нужно использовать

if (xStr == "") 
      { 
       return 0; 
      } 

тогда, чтобы получить те же результаты для списков в NaturalSortComparerList читает

if (y == "") 
     { 
      return 0; 
     } 

Я надеялся, что кто-то мог бы рационализировать эти два подхода и поделиться код. Я еще раз прокомментирую, что я относительно новичок в кодировании и включил код по существу, как написано в статьях на этом сайте. Эти два решения работают отлично, но, похоже, немного неуклюже использовать оба. Благодаря

+0

Метод сортировки возвращает отрицательное число, указывающее a b. Поэтому пустая строка должна возвращать -1. – jdweng

+0

@jdweng Я попытался изменить его на -1, как вы говорите, но в обоих случаях он помещает пустую строку в середину списка. Это не должно иметь никакого значения, но пустая строка всегда является первой записью в строке или datagrid. Может быть, поэтому это работает, когда я возвращаюсь 0 ??? –

+0

Нет ничего, что бы проверить, если x = "". Я бы сделал проверку для x == y сначала, а затем проверил x = "" – jdweng

ответ

0

Для совместного использования кода, необходимо сначала создать базовый класс, содержащий функциональные возможности

public abstract class BaseComparer : IDisposable { 
    private System.Collections.Generic.Dictionary<string, string[]> table; 

    public BaseComparer() { 
     table = new System.Collections.Generic.Dictionary<string, string[]>(); 
    } 

    public void Dispose() { 
     table.Clear(); 
     table = null; 
    } 

    public int Compare(object x, object y) { 

     System.Windows.Forms.DataGridViewRow DataGridViewRow1 = x as System.Windows.Forms.DataGridViewRow; 
     System.Windows.Forms.DataGridViewRow DataGridViewRow2 = y as System.Windows.Forms.DataGridViewRow; 

     string xStr = DataGridViewRow1 != null ? DataGridViewRow1.Cells["Column1"].Value.ToString().ToLower() : x.ToString(); 
     string yStr = DataGridViewRow2 != null ? DataGridViewRow2.Cells["Column1"].Value.ToString().ToLower() : y.ToString(); 

     if (xStr == "") { 
      return 0; 
     } 

     if (xStr == yStr) { 
      return 0; 
     } 
     string[] x1, y1; 
     if (!table.TryGetValue(xStr, out x1)) { 
      x1 = System.Text.RegularExpressions.Regex.Split(xStr.Replace(" ", ""), "([0-9]+)"); 
      table.Add(xStr, x1); 
     } 
     if (!table.TryGetValue(yStr, out y1)) { 
      y1 = System.Text.RegularExpressions.Regex.Split(yStr.Replace(" ", ""), "([0-9]+)"); 
      table.Add(yStr, y1); 
     } 

     for (int i = 0; i < x1.Length && i < y1.Length; i++) { 
      if (x1[i] != y1[i]) { 
       return PartCompare(x1[i], y1[i]); 
      } 
     } 
     if (y1.Length > x1.Length) { 
      return 1; 
     } else if (x1.Length > y1.Length) { 
      return -1; 
     } else { 
      return 0; 
     } 
    } 

    private static int PartCompare(string left, string right) { 
     int x, y; 
     if (!int.TryParse(left, out x)) { 
      return left.CompareTo(right); 
     } 

     if (!int.TryParse(right, out y)) { 
      return left.CompareTo(right); 
     } 

     return x.CompareTo(y); 
    } 
} 

Это в основном только ваш исходный код скопировать и вставить этот бит добавил:

System.Windows.Forms.DataGridViewRow DataGridViewRow1 = x as System.Windows.Forms.DataGridViewRow; 
System.Windows.Forms.DataGridViewRow DataGridViewRow2 = y as System.Windows.Forms.DataGridViewRow; 

string xStr = DataGridViewRow1 != null ? DataGridViewRow1.Cells["Column1"].Value.ToString().ToLower() : x.ToString(); 
string yStr = DataGridViewRow2 != null ? DataGridViewRow2.Cells["Column1"].Value.ToString().ToLower() : y.ToString(); 

Цель выше, чтобы определить, смотрит ли код DataGridViewRow или String, который немного неуклюжий, но он должен решить вашу проблему и предоставить вам общий код ядра.

Реализация двух компараторов затем прямо вперед, как вы унаследовали от базового класса, чтобы разделить функциональность, так что вы в конечном итоге с:

public class NaturalSortComparer : BaseComparer, System.Collections.IComparer { 

} 

и

public class NaturalSortComparerList : BaseComparer, IComparer<string> { 
    public int Compare(string x, string y) { 
     return base.Compare(x,y); 
    } 
} 
+0

Спасибо @Gary, сделал работу с несколькими хитростями, которые я добавил как еще один ответ на этот вопрос, поскольку он, кажется, представляет код лучше, чем в комментариях. –

0

Не строго говоря ответьте, но некоторые хитрости к приведенному выше, чтобы заставить его работать в моей ситуации.Первые два класса по какой-то причине обрабатываются пустые строки по-разному, так что мне пришлось изменить часть метода компаратором в классе BaseComparer читать

if (xStr == ""|yStr=="") 
      { 
       return 0; 
      } 

Там было некоторое обсуждение в комментариях по этому поводу не является правильным способ иметь дело с пустыми строками. Не знаю, почему, но кажется, что он работает, и если не включен, помещает пустую строку между записями, начинающимися с цифр и букв. Другого твика в сравнивающихся методах класса NaturalSortComparerList читать

public int Compare(string xWithCaps, string yWithCaps) 
     { 
      string x = xWithCaps.ToLower(); 
      string y = yWithCaps.ToLower(); 

      return base.Compare(x, y); 
     } 

Это было изменено, чтобы правильно обрабатывать нижние записи регистра, так как первоначально написано «test5» будет помещена выше «Test1»

Смежные вопросы