Hi.
Presumably, your objects will tend to be spread out a bit, allowing you to do some kind of clustering, e.g. via the rows in your isometric map, assigning an object to, say, whichever row it’s “above”. O(n2) can certainly grow big fast but 10 rows of 102 checks (1000) would be an improvement over one big 1002 (10,000) situation. Of course you’d need to take some special care between neighboring clusters (and deal with “big” objects that can at least visually overlap several) and find ways to deal with objects that straddle the boundaries.
Also, are you using just one display group? It might make sense to make several of those as well, e.g. one per row in the above. For that matter, are you accessing the objects directly from the display group? At the 10,000 comparisons stage, it might start to matter all on its own that you’re constantly incurring the cost of the group’s __index metamethod and more important still, all the insert()'s will probably be doing signifcant data structure maintenance: if I had to guess, I’d say groups use C++'s std::vector under the hood (whether this is true or not, alternative data structures simply put a different spin on the problem), which can move large swaths of values to open / fill gaps (if an object is inserted at position 3, objects 4 through 100 must first be moved up one spot; if object 7 is removed, objects 8 through 100 are moved down one; and moving an object around in the same vector entails both of these).
If you’ll be moving the objects around and calculating their costs anyhow, one way to do the sort is to stuff them into a priority queue and then pull them out in order. This thread has some good discussion (and some implementations, e.g. a skew heap and maybe a binary heap too): http://lua-users.org/lists/lua-l/2008-03/msg00498.html