multi_key_sort

A simple interface for multi-key and mullti-directional sorting-- the Python way


Keywords
sort, multi-key, multi-direction
License
Other
Install
pip install multi_key_sort==0.0.1

Documentation

NAME multi_key_sort

MODULE multi_key_sort

DESCRIPTION Module: multi_key_sort Contains functions for multiple-key, multiple-direction sort of iterable data

Author: HAP Proctor
Email: 48.41.50@gmail.com
GitHub: https://github.com/48-41-50/python-multi-key-sort

FUNCTIONS asorted(iterable, *keys) asorted(iterable, *keys) -> new sorted list This sort will perform a Pythonic stable sort on the iterable using operator.attrgetter and based on the keys.

    Each key is a keyspec which is:
        directional-prefix: ''
        directional-prefix: '-'
        directional-prefix: '+'
        
        directional-suffix: ''
        directional-suffix: ' desc'
        directional-suffix: ' asc'
        
        key-string:         any valid key string
        
        keyspec: directional-prefix key-string directional-suffix
        
    So if you had data in a list of classes like this:
        class SomeObj(object):
            def __init__(self, name, age, sex):
                self.name = name
                self.age = age
                self.sex = sex
        
        data = [
                SomeObj('Jim', 35, 'M'),
                SomeObj('Sarah', 20, 'F'),
                SomeObj("Alex", 35, 'M'),
                SomeObj('Bill', 40, 'M'),
                SomeObj('Wallace', 20, 'M'),
                SomeObj('Linda', 25, F')
                ]
    and you wanted to sort descending by age and ascending by name,
    valid keyspecs would be:
        '-age' or 'age desc'
        'name' or '+name' or 'name asc'
    
    Ascending sort is default so the '+' and ' asc' directionals are optional.
    
    Given all of the above, the call to asorted would be like this:
        asorted(data, 'age desc', 'name')
    and return a new list of the dictionaries sorted by the keys and directionals.

complex_sorted(iterable, getter, *keys)
    complex_sorted(iterable, getter, *keys) -> new sorted list
    This sort will perform a Pythonic stable sort on the iterable and 
    the getter and  based on the keys.
    
    The getter must be either operator.itemgetter or operator.attrgetter
    
    Each key is a keyspec which is:
        directional-prefix: ''
        directional-prefix: '-'
        directional-prefix: '+'
        
        directional-suffix: ''
        directional-suffix: ' desc'
        directional-suffix: ' asc'
        
        key-string:         any valid key string
        
        keyspec: directional-prefix key-string directional-suffix
        
    So if you had data in a list of dictionaries like this:
        data = [
                {'name': 'Jim', 'age': 35, 'sex': 'M'},
                {'name': 'Sarah', 'age': 20, 'sex': 'F'},
                {'name': "Alex", 'age': 35, 'sex': 'M'},
                {'name': 'Bill', 'age': 40, 'sex': 'M'},
                {'name': 'Wallace', 'age': 20, 'sex': 'M'},
                {'name': 'Linda', 'age': 25, 'sex': 'F'}
                ]
    and you wanted to sort descending by age and ascending by name,
    valid keyspecs would be:
        '-age' or 'age desc'
        'name' or '+name' or 'name asc'
    
    Ascending sort is default so the '+' and ' asc' directionals are optional.
    
    Given all of the above, the call to complex_sorted would be like this:
        ...
        from operator import itemgetter
        ...
        complex_sorted(data, itemgetter, 'age desc', 'name')
    and return a new list of the dictionaries sorted by the keys and directionals.

flatten_all(obj, res=None)
    This will flatten a list of lists or a mix of elements and lists 
    into a single list. It will flatten ALL levels.
    
    Ex:
        flatten_all([1, [2, [3, 4]], 5]) -> [1, 2, 3, 4, 5]

isorted(iterable, *keys)
    isorted(iterable, *keys) -> new sorted list
    This sort will perform a Pythonic stable sort on the iterable using 
    operator.itemgetter and based on the keys.
    
    Each key is a keyspec which is:
        directional-prefix: ''
        directional-prefix: '-'
        directional-prefix: '+'
        
        directional-suffix: ''
        directional-suffix: ' desc'
        directional-suffix: ' asc'
        
        key-string:         any valid key string
        
        keyspec: directional-prefix key-string directional-suffix
        
    So if you had data in a list of dictionaries like this:
        data = [
                {'name': 'Jim', 'age': 35, 'sex': 'M'},
                {'name': 'Sarah', 'age': 20, 'sex': 'F'},
                {'name': "Alex", 'age': 35, 'sex': 'M'},
                {'name': 'Bill', 'age': 40, 'sex': 'M'},
                {'name': 'Wallace', 'age': 20, 'sex': 'M'},
                {'name': 'Linda', 'age': 25, 'sex': 'F'}
                ]
    and you wanted to sort descending by age and ascending by name,
    valid keyspecs would be:
        '-age' or 'age desc'
        'name' or '+name' or 'name asc'
    
    Ascending sort is default so the '+' and ' asc' directionals are optional.
    
    Given all of the above, the call to isorted would be like this:
        isorted(data, 'age desc', 'name')
    and return a new list of the dictionaries sorted by the keys and directionals.

msort(self, *keys)
    If you subclass from a iterable base class, you can add this method 
    to an instance or to the class.
    If you subclass from list, it will act like list.sort() except it will return
    a reference to the instance.
    If you do not subclass from list, it will return a new sorted list.
    
    You will have to set a class or instance attribute named 'getter' to either
    operator.itemgetter or operator.attrgetter depending on the data being sorted.
    
    This sort will perform a Pythonic stable sort on the iterable using 
    the getter set by the instance or class attribute 'getter' and based on the keys.
    
    Each key is a keyspec which is:
        directional-prefix: ''
        directional-prefix: '-'
        directional-prefix: '+'
        
        directional-suffix: ''
        directional-suffix: ' desc'
        directional-suffix: ' asc'
        
        key-string:         any valid key string
        
        keyspec: directional-prefix key-string directional-suffix
        
    So if you had data in a list of classes like this:
        class SomeObj(object):
            def __init__(self, name, age, sex):
                self.name = name
                self.age = age
                self.sex = sex
        
        data = [
                SomeObj('Jim', 35, 'M'),
                SomeObj('Sarah', 20, 'F'),
                SomeObj("Alex", 35, 'M'),
                SomeObj('Bill', 40, 'M'),
                SomeObj('Wallace', 20, 'M'),
                SomeObj('Linda', 25, F')
                ]
    and you wanted to sort descending by age and ascending by name,
    valid keyspecs would be:
        '-age' or 'age desc'
        'name' or '+name' or 'name asc'
    
    Ascending sort is default so the '+' and ' asc' directionals are optional.
    
    Given all of the above, the call to the method (assuming it was bound as 'msort') 
    would be like this:
        self.msort('age desc', 'name')
    and return a new list of the dictionaries sorted by the keys and directionals.