Suppose I have a nested tuple as follows:
a = (((1, 2), 2), 3)
I know we could use a[0][0][1] to acquire the second element 2. However, this method might be inefficient with a long tuple. Is there any more efficient way to acquire the tuple element in this case?
You may write function for access tuple value
a = (((1, 2), 2), 3)
def access(obj, indexes):
a = obj
for i in indexes:
try:
a = a[i]
except IndexError:
return None
# except TypeError:
# when you try to index deeper than the object supports
# a is not constrained to be a scalar, it may still be dimensional
# if insufficient indexes were passed.
return a
print(access(a,(0,0,0)))
print(access(a,(0,0)))
Output
1
(1, 2)
If you want to be able to do this dynamically and know that your indices are valid you can use functools.reduce to write this compactly:
from functools import reduce
reduce(lambda it, idx: it[idx], [0, 0, 1], a) # returns 2
Related
Given,
import itertools as it
def foo():
idx = 0
while True:
yield idx
idx += 1
k = foo()
When I use zip() as in the following,
>>> list(zip(k,[11,12,13]))
[(0, 11), (1, 12), (2, 13)]
and then immediately after,
>>> list(zip(k,[11,12,13]))
[(4, 11), (5, 12), (6, 13)]
Notice that the second zip should have started with (3,11) but it jumped to (4,11)
instead. It's as if there is another hidden next(k) somewhere. This does not happen when I use it.islice
>>> k = foo()
>>> list(it.islice(k,6))
[0, 1, 2, 3, 4, 5]
Notice it.islice is not missing the 3 term.
I am using Python 3.8.
zip basically (and necessarily, given the design of the iterator protocol) works like this:
# zip is actually a class, but we'll pretend it's a generator
# function for simplicity.
def zip(xs, ys):
# zip doesn't require its arguments to be iterators, just iterable
xs = iter(xs)
ys = iter(ys)
while True:
x = next(xs)
y = next(ys)
yield x, y
There is no way to tell if ys is exhausted before an element of xs is consumed, and the iterator protocol doesn't provide a way for zip to put x "back" in xs if next(ys) raises a StopIteration exception.
For the special case where one of the input iterables is sized, you can do a little better than zip:
import itertools as it
from collections.abc import Sized
def smarter_zip(*iterables):
sized = [i for i in iterables if isinstance(i, Sized)]
try:
min_length = min(len(s) for s in sized)
except ValueError:
# can't determine a min length.. fall back to regular zip
return zip(*iterables)
return zip(*[it.islice(i, min_length) for i in iterables])
It uses islice to prevent zip from consuming more from each iterator than we know is strictly necessary. This smarter_zip will solve the problem for the case posed in the original question.
However, in the general case, there is no way to tell beforehand whether an iterator is exhausted or not (consider a generator yielding bytes arriving on a socket). If the shortest of the iterables is not sized, the original problem still remains. For solving the general case, you may want to wrap iterators in a class which remembers the last-yielded item, so that it can be recalled from memory if necessary.
I am trying to create a function that will take a tuple and remove the first instance of a value. For example:
print(Remove((0, 1, 2, 1, 3), 1))
should return (0, 2, 1, 3).
I am using functional programming and not using any predefined functions. I'm allowed to use only lambda, filter, map, and reduce but nothing else. I can't use list.remove or for-loops.
I assume a filter function will work best for this. I have figured out that the following function will work to remove all instances of the value E. I now need to know how to just remove the first instance of E.
def Remove(T,E):
return tuple(filter(lambda x: x!=E, T))
This can be done with simple recursion
If the input tuple, t, is empty, return the empty result
(inductive) Otherwise t is not empty - t has at least one element. If the first element of t matches the element to remove, x, return the tail of the tuple
(inductive) Otherwise, t is not empty and the first element of t does not match the element to remove, x. Create a new tuple with the first element of t and the recursive result
Numbered comments below correspond to the explanation above -
def remove(t, x):
if not t: # 1
return ()
elif t[0] == x: # 2
return t[1::]
else: # 3
return (t[0], *remove(t[1::], x))
print(remove((0, 1, 2, 1, 3), 1))
# (0, 2, 1, 3)
Python has an eccentric syntax for interacting with elements of collections. By defining a few helper functions, we can establish a robust and consistent way of writing this kind of program -
def is_empty(x):
return not x
def head(x):
if is_empty(x)
raise RuntimeError("head called on empty input")
else:
return x[0]
def tail(x):
if is_empty(x)
raise RuntimeError("tail called on empty input")
else:
return x[1::]
def remove(t, x):
if is_empty(x):
return ()
elif head(t) == x:
return tail(t)
else:
return (head(t), *remove(tail(t), x))
print(remove((0, 1, 2, 1, 3), 1))
# (0, 2, 1, 3)
numbers = (2, 3, 1, 4, 2, 3, 6)
e = 3 # element to remove
nums_removed = tuple(
filter(
lambda x, found=[False, True]: not (not found[0] and x == e and found.reverse() is None),
numbers
)
)
print(nums_removed)
Output:
(2, 1, 4, 2, 3, 6)
However, I can't understand why someone would want to write code so bad. It's like going from USA to USA via India.
The point is to use functional programming when it produces a simpler and more beautiful code and use anything else that is already available to make life easier.
I ended up writing a lambda function which I myself don't really understand completely, but it works. I kept trying different approaches to see what works because I was bored. You can't have local variables inside lambda functions, so I used a mutable default argument found to save function state. I posted it as an answer as soon as it worked.
If someone wants to add an explanation to my answer, feel free to edit it.
I'm trying to solve the problem from the Rosalind.
Return: The total number of signed permutations of length n, followed by a list of
all such permutations (you may list the signed permutations in any order).
I have an idea for a solution in Python, but I cannot implement it to the end. Consider for example that n = 2.
numbers = [1, -1, 2, -2]
ordering = permutations(numbers,n)
So now I've got some tuples as a result:
(1, -1) (1, 2) (1, -2) (-1, 1) (-1, 2) (-1, -2) (2, 1) (2, -1) (2, -2) (-2, 1)
(-2, -1) (-2, 2)
I need to exclude those that have elements of equal modulus. For example, (-1, 1). Is it possible to implement this, and if possible, how?
A pythonic solution using list comprehension:
filtered_perms = [(x,y) for x,y in ordering if abs(x) != abs(y)]
Edit:
Code that works fine with python 3.7:
import itertools as itt
# create permutation generator object
perms = itt.permutations([-2, -1, 1, 2], 2)
# here generator is turned into a list with certain permutations excluded
filtered_perms = [(x,y) for x,y in perms if abs(x) != abs(y)]
# print whole list
print(filtered_perms)
# print first permutation
print(filtered_perms[0])
# print length of the list
print(len(filtered_perms))
Edit2:
To fix the problem with no elements in ordering:
ordering = list(itertools.permutations([-2, -1, 1, 2],2))
after that, ordering will be a list of all elements from itertools.permutations.
The solutions proposed before are right, but if in the case that you want to process the resulting list after generating the permutations would be a nice idea to have a generator instead of a list. For that, I recommend you to design your own generator function based on itertools.permutations:
def signed_permutations(iterable, r=2):
for item in permutations(iterable, r):
if abs(item[0]) != abs(item[1]):
yield item
And you can use it as:
for item in signed_permutations(numbers):
do_something(item)
Or if you just want to create a list:
sigperm = list(signed_permutations(numbers))
The filter function is probably what you're looking for.
list(filter(lambda pair: abs(pair[0]) != abs(pair[1]), ordering))
The condition might be wrong, I'm not sure what you mean by equal modulus.
I'm trying to figure out why this doesn't return the 3rd element.
Input:
t = [(3,300),(1,100),(2,200),(4,400),(5,500)]
t.sort()
print(t)
t = t[0:2]
print(t)
Output:
[(1, 100), (2, 200), (3, 300), (4, 400), (5, 500)]
[(1, 100), (2, 200)]
Thanks! And sorry for the simple question. I would have expected the result to be:
[(1, 100), (2, 200),(3,300)]
The notation is like this A[a:b] where A is an array, a is the start point (zero indexed and an integer), and b is the stop point (also an integer and zero indexed). The last element in the selection, IE the one found at the stop point, is not captured so if the stop point is the same as the start point, no elements are captured.
So if I have A=[0,1,2,3] and type A[0:0] I get []. But If I type A[0:1] I get [0]. Note that A[:1] is the same as A[0:1] is the same as [A[1]]. If you just want the first 3 elements, try A[:3].
What's happening?
Underneath, when you call object[a:b:c] it is interpreted as object.__getitem__( slice(a, b, c) ).
Note that the slice class has the following instantiation call: slice(start, stop, step). This allows it to skip over elements or reverse order if you give it a negative step and switch the start and stop. So A[slice(None,None,-1)] is the same as A[::-1] which selects the entire array by iterating through it backwards, thus returning the entire list in reverse order. For more on slice notation see: Explain Python's slice notation
Python indices start from 0, so if you need the first three you would need the items at t[0], t[1] and t[2]. you should do as follows.
t = [(3,300),(1,100),(2,200),(4,400),(5,500)]
t.sort()
print(t)
t = t[0:3]
print(t)
I'm following a couple of Pythone exercises and I'm stumped at this one.
# C. sort_last
# Given a list of non-empty tuples, return a list sorted in increasing
# order by the last element in each tuple.
# e.g. [(1, 7), (1, 3), (3, 4, 5), (2, 2)] yields
# [(2, 2), (1, 3), (3, 4, 5), (1, 7)]
# Hint: use a custom key= function to extract the last element form each tuple.
def sort_last(tuples):
# +++your code here+++
return
What is a Tuple? Do they mean a List of Lists?
The tuple is the simplest of Python's sequence types. You can think about it as an immutable (read-only) list:
>>> t = (1, 2, 3)
>>> print t[0]
1
>>> t[0] = 2
TypeError: tuple object does not support item assignment
Tuples can be turned into new lists by just passing them to list() (like any iterable), and any iterable can be turned into a new tuple by passing it to tuple():
>>> list(t)
[1, 2, 3]
>>> tuple(["hello", []])
("hello", [])
Hope this helps. Also see what the tutorial has to say about tuples.
Why are there separate tuple and list data types? (Python FAQ)
Python Tuples are Not Just Constant Lists
Understanding tuples vs. lists in Python
A tuple and a list is very similar. The main difference (as a user) is that a tuple is immutable (can't be modified)
In your example:
[(2, 2), (1, 3), (3, 4, 5), (1, 7)]
This is a list of tuples
[...] is the list
(2,2) is a tuple
A tuple is a sequence of immutable Python objects. Tuples are sequences, just like lists. The differences between tuples and lists are, the tuples cannot be changed unlike lists and tuples use parentheses, whereas lists use square brackets.
Creating a tuple is as simple as putting different comma-separated values. Optionally you can put these comma-separated values between parentheses also. For example −
tup1 = ('Dog', 'Cat', 2222, 555555);
tup2 = (10, 20, 30, 40, 50 );
tup3 = "a", "b", "c", "d";
The empty tuple is written as two parentheses containing nothing −
tup1 = ();
To write a tuple containing a single value you have to include a comma, even though there is only one value −
tup1 = (45,);
Like string indices, tuple indices start at 0, and they can be sliced, concatenated, and so on.
The best summary of the differences between lists and tuples I have read is this:
One common summary of these more interesting, if subtle, differences is that tuples are heterogeneous and lists are homogeneous. In other words: Tuples (generally) are sequences of different kinds of stuff, and you deal with the tuple as a coherent unit. Lists (generally) are sequences of the same kind of stuff, and you deal with the items individually.
From: http://news.e-scribe.com/397
Tuples are used to group related variables together. It's often more convenient to use a tuple rather than writing yet another single-use class. Granted, accessing their content by index is more obscure than a named member variable, but it's always possible to use 'tuple unpacking':
def returnTuple(a, b):
return (a, b)
a, b = returnTuple(1, 2)
In Python programming, a tuple is similar to a list. The difference between them is that we cannot change the elements of a tuple once it is assigned whereas in a list, elements can be changed.
data-types-in-python