Reverse AND inverse python3.x OrderedDict efficiently
Question: After many attempts to create one-liners that will invert key-value pairs, and
reverse an OrderedDict, I have this:

    
    
        from collections import OrderedDict as OD
    
        attributes=OD((('brand','asus'), ('os','linux'), ('processor','i5'), ('memory','4G')))
        print(attributes)
    
        reversed_attributes=OD(reversed(list(attributes.items())))
        print(reversed_attributes)
    
        inverted_attributes=OD([reversed(item) for item in attributes.items()])
        print(inverted_attributes)
    
        ''' Prints 
            OrderedDict([('brand', 'asus'), ('os', 'linux'), ('processor', 'i5'), ('memory', '4G')])
            OrderedDict([('memory', '4G'), ('processor', 'i5'), ('os', 'linux'), ('brand', 'asus')])
            OrderedDict([('asus', 'brand'), ('linux', 'os'), ('i5', 'processor'), ('4G', 'memory')])
        '''
    

This works, but is it inefficient? By using reversed(list(a.items())) is this
creating a lot of overhead, and so is not pythonic? Same for the
inverted_attributes.

The point was to avoid for loops and so on, but will this decrease performance
as we scale up?


Answer: interesting I also came up with other ways.

    
    
    >>> from collections import OrderedDict as OD
    >>> attributes = OD((('brand','asus'), ('os','linux'), ('processor','i5'), ('memory','4G')))
    

if you want to reverse you can do this

    
    
    >>> reverse = OD(attributes.items()[::-1])
    

or a more pythonic approach:

    
    
    >>> reverse = OD(reversed(attributes.items()))
    

note you don't need to create `list` items is already a list, and while
`reversed` is a generator `OrderedDict` will simply iterate through to it
generate the new dict.  

both generating similar timings.

    
    
    $ python -m timeit "from collections import OrderedDict as OD; attributes = OD((('brand','asus'), ('os','linux'), ('processor','i5'), ('memory','4G')))" "reverse = OD(attributes.items()[::-1])"
    10000 loops, best of 3: 54.8 usec per loop
    $ python -m timeit "from collections import OrderedDict as OD; attributes = OD((('brand','asus'), ('os','linux'), ('processor','i5'), ('memory','4G')))" "reverse = OD(reversed(attributes.items()))"
    10000 loops, best of 3: 54.4 usec per loop
    $ python -m timeit "from collections import OrderedDict as OD; attributes = OD((('brand','asus'), ('os','linux'), ('processor','i5'), ('memory','4G')))" "reversed_attributes=OD(reversed(list(attributes.items())))"
    10000 loops, best of 3: 54.4 usec per loop
    

if you want to invert:

    
    
    >>> invert = OD(zip(*zip(*attributes.items())[::-1]))
    

or more pythonic:

    
    
    >>> invert = OD(map(reversed, attributes.items()))
    

again both generating similar timings.

    
    
    $ python -m timeit "from collections import OrderedDict as OD; attributes = OD((('brand','asus'), ('os','linux'), ('processor','i5'), ('memory','4G')));" "invert = OD(zip(*zip(*attributes.items())[::-1]))"
    10000 loops, best of 3: 57 usec per loop
    $ python -m timeit "from collections import OrderedDict as OD; attributes = OD((('brand','asus'), ('os','linux'), ('processor','i5'), ('memory','4G')));" "invert = OD(map(reversed, attributes.items()))"
    10000 loops, best of 3: 56.8 usec per loop
    $ python -m timeit "from collections import OrderedDict as OD; attributes = OD((('brand','asus'), ('os','linux'), ('processor','i5'), ('memory','4G')));" "inverted_attributes=OD([reversed(item) for item in attributes.items()])"
    10000 loops, best of 3: 55.8 usec per loop
    

you can use the two methods in conjunction to both reverse and invert.

> This works, but is it inefficient? By using reversed(list(a.items())) is
> this creating a lot of overhead, and so is not pythonic? Same for the
> inverted_attributes.

something can generate a lot of overhead and be pythonic on the other hand
something can very very efficient and not be very pythonic, the term has being
a bit abused, but thats just my opinion

exert from wikipedia:

> A common neologism in the Python community is pythonic, which can have a
> wide range of meanings related to program style. To say that code is
> pythonic is to say that it uses Python idioms well, that it is natural or
> shows fluency in the language. Likewise, to say of an interface or language
> feature that it is pythonic is to say that it works well with Python idioms,
> that its use meshes well with the rest of the language.  
>  
>  In contrast, a mark of unpythonic code is that it attempts to write C++ (or
> Lisp, Perl, or Java) code in Python—that is, provides a rough transcription
> rather than an idiomatic translation of forms from another language. The
> concept of pythonicity is tightly bound to Python's minimalist philosophy of
> readability and avoiding the "there's more than one way to do it" approach.
> Unreadable code or incomprehensible idioms are unpythonic.

as for:

> but will this decrease performance as we scale up?

This hard to say, without knowing why you are making such transforms, or
whether or not their an integral part of your system, fundamentally at a bare
minimun they are adding linear time/space overhead which may or may not be
good, if the number of entries remains small, then no problem but if at every
request, assuming this happening at a web server, your are doing this on a
large dicts, this can be quite harsh, and may require a redesign to avoid
this.

