2010-04-06 4 views
3

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

[ УДАЛИТЬ] 1, [УДАЛИТЬ], 3, 2

стал бы ...

1, 2, 3, [УДАЛИТЬ], [УДАЛИТЬ]

и обратить вспять это стало бы ...

3, 2, 1, [EMPTY], [EMPTY]

Любые идеи?

 public int Compare(ListViewItem x, ListViewItem y) 
    { 
     int comparison = int.MinValue; 
     ListViewItem.ListViewSubItem itemOne = x.SubItems[subItemIndex]; 
     ListViewItem.ListViewSubItem itemTwo = y.SubItems[subItemIndex]; 

     if (!string.IsNullOrEmpty(itemOne.Text) && !string.IsNullOrEmpty(itemTwo.Text)) 
     { 
      uint itemOneComparison = uint.Parse(itemOne.Text); 
      uint itemTwoComparison = uint.Parse(itemTwo.Text); 

      comparison = itemOneComparison.CompareTo(itemTwoComparison); 
     } 
     else 
     { 
      // ALWAYS SEND TO BOTTOM/END OF LIST. 
     } 

     // Calculate correct return value based on object comparison. 
     if (OrderOfSort == SortOrder.Descending) 
     { 
      // Descending sort is selected, return negative result of compare operation. 
      comparison = (-comparison); 
     } 
     else if (OrderOfSort == SortOrder.None) 
     { 
      // Return '0' to indicate they are equal. 
      comparison = 0; 
     } 

     return comparison; 
    } 

Cheers.

ответ

4

Ваша логика немного от: ваш else будет введен, если либо из них пусты, но вы хотите только пустые один, чтобы перейти к концу списка , а не непустой. Нечто подобное должно работать:

public int Compare(ListViewItem x, ListViewItem y) 
{ 
    ListViewItem.ListViewSubItem itemOne = x.SubItems[subItemIndex]; 
    ListViewItem.ListViewSubItem itemTwo = y.SubItems[subItemIndex]; 

    // if they're both empty, return 0 
    if (string.IsNullOrEmpty(itemOne.Text) && string.IsNullOrEmpty(itemTwo.Text)) 
     return 0; 

    // if itemOne is empty, it comes second 
    if (string.IsNullOrEmpty(itemOne.Text)) 
     return 1; 

    // if itemTwo is empty, it comes second 
    if (string.IsNullOrEmpty(itemTwo.Text) 
     return -1; 

    uint itemOneComparison = uint.Parse(itemOne.Text); 
    uint itemTwoComparison = uint.Parse(itemTwo.Text); 

    // Calculate correct return value based on object comparison. 
    int comparison = itemOneComparison.CompareTo(itemTwoComparison); 
    if (OrderOfSort == SortOrder.Descending) 
     comparison = (-comparison); 

    return comparison; 
} 

(я, возможно, уже получил «1» и «-1», когда они пусты задом наперед, я никогда не помню :)

+0

Wokred отлично. благодаря! – paulio

+0

не ухудшит ли производительность, если у него больше чисел, чем пустых? – Amsakanna

+0

@Veer: каким образом? –

0

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

Конечно, если оба пустые, вы должны вернуть 0, поскольку они равны.

0

Ваш // ВСЕГДА ОТПРАВИТЬСЯ НА НОМЕР/КОНЕЦ СПИСКА. ветвь выполняется, когда либо параметры x, либо y пусты, то есть непустое значение будет сортироваться в соответствии с этим правилом, если оно сравнивается с пустым значением. Вы, вероятно, хотите что-то больше, как это:

if (!string.IsNullOrEmpty(itemOne.Text) && !string.IsNullOrEmpty(itemTwo.Text)) 
{ 
    uint itemOneComparison = uint.Parse(itemOne.Text); 
    uint itemTwoComparison = uint.Parse(itemTwo.Text); 

    comparison = itemOneComparison.CompareTo(itemTwoComparison); 
} 
else if (!string.IsNullOrEmpty(itemOne.Text) 
{ 
    comparison = -1; 
} 
else 
{ 
    comparison = 1; 
} 
0
else 
{ 
    //ALWAYS SEND TO BOTTOM/END OF LIST. 
    if (string.IsNullOrEmpty(itemOne.Text) && string.IsNullOrEmpty(itemTwo.Text)) 
    { 
     return 0; 
    } 
    else if (string.IsNullOrEmpty(itemOne.Text)) 
    { 
     return -1; 
    } 
    else if (string.IsNullOrEmpty(itemTwo.Text)) 
    { 
     return 1; 
    } 
} 
2

я на самом деле подойти к этому совершенно по-другому, удалить пустые слоты, сортировки списка, а затем добавить пустые в конец списка

static void Main(string[] args) 
{ 
    List<string> ints = new List<string> { "3", "1", "", "5", "", "2" }; 
    CustomIntSort(ints, (x, y) => int.Parse(x) - int.Parse(y)); // Ascending 
    ints.ForEach(i => Console.WriteLine("[{0}]", i)); 

    CustomIntSort(ints, (x, y) => int.Parse(y) - int.Parse(x)); // Descending 
    ints.ForEach(i => Console.WriteLine("[{0}]", i)); 
} 
private static void CustomIntSort(List<string> ints, Comparison<string> Comparer) 
{ 
    int emptySlots = CountAndRemove(ints); 
    ints.Sort(Comparer); 
    for (int i = 0; i < emptySlots; i++) 
     ints.Add(""); 
} 
private static int CountAndRemove(List<string> ints) 
{ 
    int emptySlots = 0; 
    int i = 0; 

    while (i < ints.Count) 
    { 
     if (string.IsNullOrEmpty(ints[i])) 
     { 
      emptySlots++; 
      ints.RemoveAt(i); 
     } 
     else 
      i++; 
    } 
    return emptySlots; 
} 

Этот вопрос привлек мое внимание в последнее время, это Comparer будет делать это либо

class CustomComparer 
    : IComparer<string> 
{ 
    private bool isAscending; 
    public CustomComparer(bool isAscending = true) 
    { 
     this.isAscending = isAscending; 
    } 
    public int Compare(string x, string y) 
    { 
     long ix = CustomParser(x) * (isAscending ? 1 : -1); 
     long iy = CustomParser(y) * (isAscending ? 1 : -1); 
     return ix.CompareTo(iy) ; 
    } 
    private long CustomParser(string s) 
    { 
     if (string.IsNullOrEmpty(s)) 
      return isAscending ? int.MaxValue : int.MinValue; 
     else 
      return int.Parse(s); 
    } 
} 
Смежные вопросы