When flattening for loops, you would do something like this:
for a, b, c in itertools.product(x1, x2, x3):
...
But how would you handle the case where one of the elements is to be used as a parameter to retrieve a list also to be traversed? For example:
for a, b in itertools.product(x1, get_b_elements(a)):
...
Is this even possible?
for a in x1:
for b in get_b_elements(a):
#do something with (a, b)
Just to list an alternative:
for (a, b) in [(a_i, b_i) for a_i in x1 for b_i in get_b_elements(a_i)]:
#do something with (a, b)
As #wim notes, none of these "flatten" the loop as you want.
try this:
alphabets = [a,b,c,d]
xs = [x1,x2,x3]
itertools.product(alphabets, xs)
Related
I am using sympy to do some calculations, but I need to manipulate results of multiplications using rules I have to define. Let us suppose I have
a, b, c, d = symbols('a b c d', commutative=False)
res = a*b + b*c + c*d
I was wondering how can I write a function which takes res and gives a list of this kind
[[a,b],[b,c],[c,d]]
since every time I try to perform operations like list(res) python throws the exception Mul (Add) object is not iterable. Thanks in advance
There is no function for this already but you can make one like this:
def factors(expr):
result = []
for term in Add.make_args(expr):
flat_factors = []
for factor in Mul.make_args(term):
symbol, power = factor.as_base_exp()
flat_factors += [symbol] * power
result.append(flat_factors)
return result
That gives:
In [74]: factors(a*b + b*c + c*d)
Out[74]: [[a, b], [b, c], [c, d]]
In [75]: factors(a**2*b + a*b**2)
Out[75]: [[a, b, b], [a, a, b]]
This is a way:
[x.as_ordered_factors() for x in res.as_ordered_terms()]
No sure, but do you wanna do something like this?
res = 'a*b + b*c + c*d'
def list_func(res):
list1 = res.split('+')
return ([item.split('*') for item in list1])
print(list_func(res))
How can I generate a list of tuples whose elements are not repeated? In addition, if there is (a,b) tuple in list, (b,a) would not be generated in this list.
I use code below from here, but it doesn't provide second condition:
[tuple(i) for i in np.random.randint(5242, size=(500,2))]
I'm not sure you're going to get any kind of one-liner to do that cleanly. I'd just do something like:
num_set = set()
while len(num_set) < 500:
a, b = random.randint(0, 5242), random.randint(0, 5242)
if (b, a) not in num_set:
num_set.add((a, b))
num_list = list(num_set)
Looks like you're interested in something more like a set of sets rather than purely tuples. If your objects are sortable, you can use this common hack:
included_set = set()
included_list = list()
input_list = np.random.randint(5242, size=(500,2))
for (a, b) in input_list:
sorted_version = tuple(sorted((a, b)))
if sorted_version not in included_set:
included_set.add((a, b))
included_list.append((a, b))
If your objects are not sortable, but are hashable and comparable, you could tweak the above to work anyway:
for (a, b) in input_list:
if (a, b) not in included_set and (b, a) not in included_set:
included_set.add((a, b))
included_list.append((a, b))
Note that you only need to keep separate included_list and included_set if you want to retain the ordering of the input list. If not, and if you don't care about the tuple ordering (a, b), just use:
uniques = {tuple(sorted(tup)) for tup in input_list}
you could just use random.sample from the python built-in library:
nums = random.sample(range(5242), 1000)
res = [tuple(v) for v in zip(nums[::2], nums[1::2])]
So i'm trying to implement the agglomerative clustering algorithm and to check the distances between each cluster i use this:
a, b = None, None
c = max
for i in range(len(map)-1):
for n in range(len(map[i])):
for j in range(i+1, len(map)):
for m in range(len(map[j])):
//dist is distance func.
d = dist(map[i][n], map[j][m])
if c > d:
a, b, c = i, j, d
print(a, ' ', b)
return a, b
map looks like this: { 0: [[1,2,3], [2,2,2]], 1: [[3,3,3]], 2: [[4,4,4], [5,5,5]] }
What I expect from this is for each row item to compare with every row/col of every other row. So something like this:
comparisons:
[1,2,3] and [3,3,3], [1,2,3] and [4,4,4], [1,2,3] and [5,5,5], [2,2,2] and [3,3,3] and so on
When I run this it only works 1 time and fails any subsequent try after at line 6 with KeyError.
I suspect that the problem is either here or in merging clusters.
If map is a dict of values, you have a general problem with your indexing:
for m in range(len(map[j])):
You use range() to create numerical indices. However, what you need j to be in this example is a valid key of the dictionary map.
EDIT:
That is - of course - assuming that you did not use 0-based incremented integers as the key of map, in which cause you might as well have gone with a list. In general you seem to be relying on the ordering provided in a list or OrderedDict (or dict in Python3.6+ as an implementation detail). See for j in range(i+1, len(map)): as a good example. Therefore I would advise using a list.
EDIT 2: Alternatively, create a list of the map.keys() and use it to index the map:
a, b = None, None
c = max
keys = list(map.keys())
for i in range(len(map)-1):
for n in range(len(map[keys[i]])):
for j in range(i+1, len(map)):
for m in range(len(map[keys[j]])):
#dist is distance func.
d = dist(map[keys[i]][n], map[keys[j]][m])
if c > d:
a, b, c = i, j, d
print(a, ' ', b)
return a, b
Before accessing to map[j] check is it valid or not like:
if j in map.keys():
#whatever
or put it in try/except:
try:
#...
except KeyError:
#....
Edit:
its better to use for loop like this:
for i in map.keys():
#.....
I am trying to generate an array that is the sum of two previous arrays. e.g
c = [A + B for A in a and B in b]
Here, get the error message
NameError: name 'B' is not defined
where
len(a) = len(b) = len(c)
Please can you let me know what I am doing wrong. Thanks.
The boolean and operator does not wire iterables together, it evaluates the truthiness (or falsiness) of its two operands.
What you're looking for is zip:
c = [A + B for A, B in zip(a, b)]
Items from the two iterables are successively assigned to A to B until one of the two is exhausted. B is now defined!
It should be
c = [A + B for A in a for B in b]
for instead of and. You might want to consider using numpy, where you can add 2 matrices directly, and more efficient.
'for' does not work the way you want it to work.
You could use zip().
A = [1,2,3]
B = [4,5,6]
c = [ a + b for a,b in zip(A,B)]
zip iterates through A & B and produces tuples.
To see what this looks like try:
[ x for x in zip(A,B)]
I am trying to generate all permuations of a set of items and the my R needs to be larger than the size of the set of items
Here is an example :
itertools.permutations ("ABC", 4)
this always returns 0 items as R > N.
I want this
[A, A, A, A]
[A, A, A, B]
[A, A, B, A]
[A, B, A, A]
...
How can I achieve this?
You don't seem to want the permutation, but the Cartesian product:
itertools.product("ABC", repeat=4)
https://docs.python.org/3/library/itertools.html#itertools.product