Python Forum

Full Version: sorting
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3
in another project i ran into this issue with str vs int. but i can see potential cases where other types could be there, hence the the thought of using repr(). but i am not sure if that is even good enough. i wonder if json.dump() can handle all possible types or if pickle would be a better choice. oh wait, there are cases where even pickle can fail. the only final answer i can think of is to do try: and if there is an exception just use some fixed string like '?'.
When would str() not work? If the object doesn't have __str__, it uses __repr__, and everything has __repr__, doesn't it? You would have to explicitly override __repr__ (or __str__) to throw an error to get a class that couldn't handle str().

If you don't like the ordering str() give you, that's a problem, but it's a problem of how do you order different types. There's no objective answer for that, and whatever subjective answer you come up with could be written into a function and used with key=.
i use repr() to do printing of variables for diagnostic assistance.  it quotes actual string types so they can be recognized as strings.  but for sorting i now see that it is a bad choice where the order matters because the string content can cause the quotes to vary, or insert escape sequences, and disorganize the sorting order.

i vaguely remember there being cases where repr() failed and raised an exception with a traceback.  i do not recall what it did this on, but i probably need to add a lot of try/except code to my print_object() function.  i did not try str() on this case.  if i can recall it, i plan to play around with it in many ways.

sorting of unhashable and/or complex objects is inherently risky.  one must think about how they want their data to be ordered.  the type is likely to be as important as the value.

def pv(*names,**opts):
    p = '==>'
    for x in names:
        if not isinstance(x,(list,tuple)):
            x = [ x ]
        for name in x:
            name = str(name)
            d = inspect.currentframe().f_back.f_locals
            if name not in d:
                print(p, name, 'not assigned', **opts)
            else:
                print(p, name, '=', repr(d[name]), **opts)
    return
I did this yesterday but had no time to write here.
Didn't try for other types.
In [1]: d = {1: 'one', 4: 'four', 3: 'three', 2: 'two', 'five': 5, 'six': 6, 'nine': 9, 'ten': 10, 'eight': 8, 'seven':7, 11: 'eleven'} 

In [2]: def sorted_dict(obj):
   ...:     nums = sorted([n for n in obj.keys() if isinstance(n, int)])
   ...:     strs = sorted([s for s in obj.keys() if isinstance(s, str)])
   ...:     d_keys = nums + strs
   ...:     return [(k, obj[k]) for k in d_keys]
   ...: 

In [3]: for k, v in sorted_dict(d):
   ...:     print(k, v)
   ...:     
1 one
2 two
3 three
4 four
11 eleven
eight 8
five 5
nine 9
seven 7
six 6
ten 10
Simple sorting where numbers are sorted naturally and come before everything else could be achieved in python3 with:
In [5]: a = [3, 2.34, 1, 'string', '5th May', 11]

In [6]: sorted(a, key=lambda x: (0, x) if isinstance(x, (int, float)) else (1, str(x)))
Out[6]: [1, 2.34, 3, 11, '5th May', 'string']
As higher position elements are used only to resolve ties, it wont crash due to incomparable types.
May you explain what is (0, x) tuple for and how this one liner is doing the same?
Python tuples are sorted lexicographically (at first its sorted by first element, then second element is used to break ties, then third to break remaining ties and so on). So using (0, ..) and (1, ..) ensures that any item with key (0,..) comes before any item with key (1, ...). "Tie breaking" compares second elements only inside groups with same first element and these are comparable (for tuples starting with 0 they are all numbers, for tuples starting with 1 they are all strings), so it wont crash.
nice, so str(x) is sorted as (1,str(x)).  so is str() safe for all other possible types ... other than silliness like putting classes in with data to be sorted?
Yes, as Ichabod801 pointed out, str() should be quite secure.

But strings and other non numbers will be mixed up - you can expand this and use seperate key function that could do somethig like: x number -> (0, x), x string -> (1, x), x type A -> (2, str(x)), x type B -> (3, str(x)), x something else -> (4, str(x)) to enforce that different types would be sorted as you want. And you dont need to always use str, for some classes it could make sense to use other function. It all depends on what you want (and why).
I still don't get it. Can you convert lambda x: (0, x) if isinstance(x, (int, float)) else (1, str(x))) to a normal function, please
Pages: 1 2 3