1

I have a list of strings and lists. I want to reverse each iterable in my list using map. My current setup is as follows:

forwards_list = [
  'abc',
  'def',
  [1, 2, 3, 4, 5],
]

def reverse(item):
  object_type = type(item)
  return object_type(reversed(item))

backwards_list = list(map(reverse, forwards_list))
print(backwards_list)

Output:

['<reversed object at 0x000000000A29A5C0>',
'<reversed object at 0x000000000A29A5C0>',
[5, 4, 3, 2, 1]]

Desired Output:

['cba', 'fed', [5, 4, 3, 2, 1]]

The problem seems to be that list(reversed([])) returns [], whereas str(reversed('')) returns '<reversed object at 0x000000000A335898>' . Can anybody help?

gtlambert
  • 11,711
  • 2
  • 30
  • 48
  • Not enough rep yet to comment, but try this location: http://stackoverflow.com/questions/931092/reverse-a-string-in-python – Alea Kootz Sep 01 '15 at 22:06
  • Mixing different kinds of things (strings & lists) within the same list is almost always a bad idea. It makes them universally difficult to work with and you probably started with them being separate in the first place. – Chad S. Sep 01 '15 at 22:11

1 Answers1

6

If you're content to work only with sequences, you could use slicing rather than reversed:

def reverse(item):
    return item[::-1]

In general, sequences will return an object of the same time when slicing:

>>> 'foo'[::-1]
'oof'
>>> ['foo', 'bar', 'baz'][::-1]
['baz', 'bar', 'foo']
>>> ('foo', 'bar', 'baz')[::-1]
('baz', 'bar', 'foo')

There are a few types however where this certainly won't work (e.g. dict). However, reversed requires sequences too (or objects that have a __reversed__ method).

>>> reversed(dict.fromkeys([1,2,3], None))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument to reversed() must be a sequence

You could handle this last case by type-checking and combining with your original solution:

import collections  # Need `collections.abc` on python3.4+ IIRC
def reverse(item):
    if isinstance(item, collections.Sequence):
        return item[::-1]
    obj_type = type(item)
    return obj_type(reversed(item))

Of course, even that won't work all (most?) the time since there is no rule (or even convention) to say that the constructor of an object must accept a reversed iterator generated from another instance of that type :0).

mgilson
  • 300,191
  • 65
  • 633
  • 696