[wxPython] wxListCtrl sorting help

(I sent this last week, but I never saw it enter the list or any replies. I'm
not sure if it made it so I'm sending it again. Hope it doesn't annoy you =).

Hi,

I've implemented sorting of the ListCtrls on my app, and it seems to work just
like in the demo. The problem is that its just too slow. When there are 50
or so items it's fine but if I have 500 or so (very common) it literally takes
2 MINUTES(!) after I click the column header before my app comes back to
life.

Here's an example of the code I am using. I'm wondering if I can bolt in my
own sorting algorithm to speed things up? Is there a way to reduce the
function calls I am making? Please help =). I've already made two functions
to separate the string sorts from the numerical sorts to speed things up
slightly. the sortdirection variables let me reverse the sort on the second
col click.

def ColumnSorterNumber(self, key1, key2):

  item1 = string.atoi( self.GetItem( self.FindItemData(-1, key1), self.col
).GetText() )
  item2 = string.atoi( self.GetItem( self.FindItemData(-1, key2), self.col
).GetText() )

  if item1 == item2: return 0
  elif item1 < item2: return self.nsortdirection
  else: return self.sortdirection

def ColumnSorterString(self, key1, key2):

  item1 = self.GetItem( self.FindItemData(-1, key1), self.col ).GetText()
  item2 = self.GetItem( self.FindItemData(-1, key2), self.col ).GetText()
    
  if item1 == item2: return 0
  elif item1 < item2: return self.nsortdirection
  else: return self.sortdirection

···

----------------------------------------------------------------------------

I'd guess (and it's just a guess) that you are getting killed by the number of function calls (as you've already suspected). To get the value of each string item, you are making 3 function calls: GetItem(), FindItemData(), and GetText(). For int items you add another: string.atoi(). I assume that the sort is using something like quicksorty which requires (I hope... my CS classes were a *long* time ago) on the order of n*log(n) comparisons. Jumping from 50 to 500 leads to a *lot* more comparisons.

I tend to have ListCtrl's keep around a list with their contents so that the function calls aren't necessary to get at values. Something like this:

def __TreeListSortHelper(self,key1,key2):
   """Used by ListCtrl.SortItems
   """
   item1 = self._examples[key1][self._treeSortCol]
   item2 = self._examples[key2][self._treeSortCol]

   if self.treeSortOrders[self._treeSortCol]:
     item2,item1=item1,item2
   if item1 == item2:
     return 0
   elif item1 < item2:
     return -1
   else:
     return 1

where self._examples carries around the internal data and self._treeSortCol is the column on which the sort is taking place.

  I hope this helps,
-greg

···

At 12:13 PM 8/24/2000, Mike Miller wrote:

I've implemented sorting of the ListCtrls on my app, and it seems to work just
like in the demo. The problem is that its just too slow. When there are 50
or so items it's fine but if I have 500 or so (very common) it literally takes
2 MINUTES(!) after I click the column header before my app comes back to
life.

Here's an example of the code I am using. I'm wondering if I can bolt in my
own sorting algorithm to speed things up? Is there a way to reduce the
function calls I am making? Please help =). I've already made two functions
to separate the string sorts from the numerical sorts to speed things up
slightly. the sortdirection variables let me reverse the sort on the second
col click.

----
greg Landrum (greglandrum@earthlink.net)
Software Carpenter/Computational Chemist