I have a tuple and would like to reverse it in Python.
The tuple looks like this : (2, (4, (1, (10, None)))).
I tried reversing in Python by:
a = (2, (4, (1, (10, None))))
b = reversed(a)
It returns me this:
<reversed object at 0x02C73270>
How do I get the reverse of a? Or must I write a function to do this?
The result should look like this:
((((None, 10), 1), 4), 2)
def my_reverser(x):
try:
x_ = x[::-1]
except TypeError:
return x
else:
return x if len(x) == 1 else tuple(my_reverser(e) for e in x_)
Try this deep-reverse function:
def deep_reverse(t):
return tuple(deep_reverse(x) if isinstance(x, tuple) else x
for x in reversed(t))
This will handle arbitrarily nested tuples, not just two-tuples.
As explained in the documentation, the reversed function returns an iterator (hence the <reversed at ...>). If you want to get a list or a tuple out of it, just use list(reversed(...)) or tuple(reversed(...)).
However, it's only part of our problem: you'll be reversing the initial object (2, (...)) as (...,2), while the ... stays the same. You have to implement a recursive reverse: if one element of your input tuple is an iterable, you need to reverse it to.
It does not make sense to do this with reversed, sorry. But a simple recursive function would return what you want:
def reversedLinkedTuple(t):
if t is None:
return t
a, b = t
return reversedLinkedTuple(b), a
reversed is usable only on reversible iterable objects like lists, tuples and the like. What you are using (a linked list) isn't iterable in the sense of the Python built-in iter.
You could write a wrapping class for your linked list which implements this and then offers a reverse iterator, but I think that would be overkill and would not really suit your needs.
def reverse(x):
while x >= 0:
print(x)
x = x = 1
reverse(x)
Related
Why does this:
seq = [(1, 2), (3, 4), (5, 6)]
print(() in seq)
return False? How can I check if there's a tuple, or even a generic sequence, inside a sequence with no specific values, as in this answer.
() is an empty tuple. seq does not contain an empty tuple.
You want
>>> seq = [(1, 2), (3, 4), (5, 6)]
>>> any(isinstance(x, tuple) for x in seq)
True
For a generic sequence you can use
>>> from collections import abc
>>> any(isinstance(x, abc.Sequence) for x in seq)
True
However, lots of objects are informally treated as sequences but neither implement the full protocol abc.Sequence defines nor register as a virtual subclass of Sequence.
Read this excellent answer for additional information.
You can find a question about detecting sequences here.
What you are checking is the existence of an empty tuple in the list.
You can check the type instead.
def has_tuple(seq):
for i in seq:
if isinstance(i, tuple):
return True
return False
I have a tuple like (p1, p2) (for example (5,3) or (2,1))
I want to apply the same operation to each element of the tuple. (Incidentally this operation will give for each element another tuple, so I will have a tuple of tuples but this is not a necessary condition)
First I thought something like
for element in (3,2):
res=function(element)
but first, this doesn't seem a elegant solution and two, I would still have to form a tuple from each res to get a (function(3),function(2)) solution
How can I apply a function (with several arguments) to each element of the tuple once and get a tuple of returned values?
If I understand you question correctly, map should to the job as well:
tuple(map(func, tpl))
where func is a one-argument function you defined.
Now, if you have a function with several arguments you would like to apply to each element, like:
def func(x, y, z): return x*y+z
I assume that 2 elements (let's take y and z) are fixed, while x will be determined by the value in the tuple.
There are two approaches in my view:
Either you define a new function with 2 fixed arguments and map:
def func1(x): return func(x, 3, 2)
tuple(map(func1, tpl))
Or map as follows (I think it is less elegant, but it is a matter of tastes, maybe):
tuple(map(lambda x: func(x, 3, 2), tpl))
One approach uses a list comprehension:
def add_one(x):
return x + 1
tpl = (5, 3)
output = tuple([add_one(x) for x in tpl])
print(output) # (6, 4)
You may consider using the generator comprehension then convert it to tuple:
>>> data = (3, 5, 7, 9)
>>> tuple((function(x) for x in data))
em...I feel confused about this code, I am really new to coding, and wonder anyone can help:
def takeSecond(elem):# If I pass the argument as a list, why don't I need to specify it here?
return elem[1] # what return elem[1] means,does it return the y in (x,y)? but why!?
random = [(2, 2), (3, 4), (4, 1), (1, 3)]
random.sort(key=takeSecond) # key = takeSecond what is this even mean lol?..
print('Sorted list:', random)
Let's say you have a list of items, which contains:
list = [a,b,c]
If you use the following piece of code:
def func():
return list[1]
You'd get "b" as output. The number "1" is not the first element, it's the second element. The counting in python starts at 0. So basically, if you want to access "a", you have to use:
def func():
return list[0]
Because 0 = a, 1 = b, 2 = c, and so on. If you change return elem[1] to return elem[0] you get the variable x.
Here your trying to sort based on second value in given list
takeSecond function is always returns the second value in the given element.
In random.sort() method calling with your passing key parameter as takeSecond function, which means sorting perform based on that element it happen. In our case it will return second element. So sorting is perform based on second element
And then printing the sorted list
I've written a function that accepts, works and return simple, non-nested tuples.
eg.:
myfun((1,2,3,4)):
... -> logic
return (1,2,3,4) -> the numbers can change, but the shape will be the same
Since the logic works only with mono-dimensional tuples but is conceptually the same for each level of nesting. I was wondering if there's a way to convert a nested tuple like ((1,2,(3,)),(4,)) into the plain (1,2,3,4) and then convert it back to ((1,2,(3,)),(4,)).
Basically what I want is to unpack a generic input tuple, work with it, and then pack the results in the same shape of the given one.
Is there a Pythonic way to accomplish such a task?
Probably the unpacking could be solved with recursion, however I'm not sure about the "re-packing" part.
The unpacking is not that hard:
def unpack(parent):
for child in parent:
if type(child) == tuple:
yield from unpack(child)
else:
yield child
for example, can do the trick.
Repacking is a bit trickier. I came up with the following, which works but is not very pythonic, I'm afraid:
def repack(structured, flat):
output = []
global flatlist
flatlist = list(flat)
for child in structured:
if type(child) == tuple:
output.append(repack(child, flatlist))
else:
output.append(flatlist.pop(0))
return tuple(output)
Example usage is:
nested = ((1, 2, (3,)), (4,))
plain = tuple(unpack(nested))
renested = repack(nested, plain)
Hope this helps!
This should work for the repacking:
x = (1,(2,3),(4,(5,6)))
y = (9,8,7,6,5,4)
def map_shape(x, y, start=0):
if type(x) == tuple:
l = []
for item in x:
mapped, n_item = map_shape(item, y[start:])
start += n_item
l.append(mapped)
return tuple(l), start
else:
return y[start], start+1
map_shape(x,y)[0]
Output:
(9, (8, 7), (6, (5, 4)))
I submit my version. It uses the same function to flat and reconstruct the list. If flat is None it flattens, otherwise it reconstructs by yielding a tuple.
import collections
def restructure(original, flat=None):
for el in original:
if isinstance(el, collections.Iterable) and not isinstance(el, (str, bytes)):
if flat:
yield tuple(restructure(el, flat))
else:
yield from restructure(el)
else:
yield next(flat) if flat else el
def gen():
i = 0
while True:
yield i
i += 1
def myfun(iterable):
flat = tuple(restructure(iterable))
# your transformation ..
flat = gen() # assigning infinite number generator for testing
return restructure(iterable, flat=iter(flat))
x = (1, (2, 3), (4, (5, 6)))
print(tuple(y for y in myfun(x))) # (0, (1, 2), (3, (4, 5)))
>>> b=[('spam',0), ('eggs',1)]
>>> [reversed(x) for x in b]
[<reversed object at 0x7fbf07de7090>, <reversed object at 0x7fbf07de70d0>]
Bummer. I expected to get a list of reversed tuples!
Sure I can do:
>>> [tuple(reversed(x)) for x in b]
[(0, 'spam'), (1, 'eggs')]
But I hoped for something generic? Smth that when being handed over a list of tuples, returns a list of reversed tuples, and when handed over a list of lists, returns a list of reversed lists.
Sure, an ugly hack with isinstance() is always available but I kind of hoped avoiding going that route.
Extended slicing.
[x[::-1] for x in b]
If you only need depth of one, try [x[::-1] for x in mylist]. Otherwise just make a recursive function like
import collections
def recursive_reversed(seq):
if isinstance(seq, collections.Sequence):
return [recursive_reversed(x) for x in reversed(seq)]
return seq
That function actually converts all of the sequences to lists, but you get the gist, I hope.