Python: Avoid using multiple nested for loops to iterate over strings - python

Is there a simpler way to iterate over multiple strings than a massive amount of nested for loops?
list = ['rst','uvw','xy']
for x in list[0]:
for y in list[1]:
for z in list[2]:
print x+y+z
rux
ruy
...
tvx
tvy
twx
twy
Example list I really want to avoid typing writing loops for:
list = ['rst','uvw','xy','awfg22','xayx','1bbc1','thij','bob','thisistomuch']

You need itertools.product:
import itertools
list = ['rst','uvw','xy','awfg22','xayx','1bbc1','thij','bob','thisistomuch']
for x in itertools.product(*list):
print(''.join(x))
product returns all possible tuples of elements from iterators it gets. So
itertools.product('ab', 'cd')
will return a generator, yielding ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd')

You are looking for the product function from itertools:
import itertools
lst = ['rst','uvw','xy']
[''.join(s) for s in itertools.product(*lst)]
# ['rux',
# 'ruy',
# 'rvx',
# 'rvy',
# 'rwx',
# ...
# 'twx',
# 'twy']

Another way? Definitely. Simpler? Maybe not...
I'm guessing it's because you don't necessarily know how many strings you'll have in your list.
What about:
sl = ['abc','mno','xyz']
def strCombo(l,s=''):
if(len(l)==0):
return s
elif(len(l)==1):
return [(s+x) for x in l[0]]
else:
return [strCombo(l[1:],(s+x)) for x in l[0]]
final = []
for x in strCombo(sl)[0]:
final = final + x

Related

How do you find the sum of specific items in a 2d array with a foreach loop?

I have this list:
my_list = [('a',1), ('b',2), ('c',3)]
How can i write a foreach loop to find the sum of 1+2+3?
Simplest approach:
list = [('a',1), ('b',2), ('c',3)]
summ = 0 # variable to store sum
for i in list:
summ = summ + i[1]
print(summ)
This returns 6
Short approach using a comprehension:
items = [('a', 1), ('b', 2), ('c', 3)]
print(sum(item[1] for item in items))
Please avoid naming your list list, it's the name of the list type in Python, so you're "hiding" the list type, which can cause strange bugs if you need the real list later.

Include For loop inside function for processing list of tuples

I have a function to process the list of tuples. What is the easiest way to include for loop inside the function itself? I am fairly new to python, trying to convert this in OOP function. Any help will be appreciated.
My current solution:
tups = [(1,a),(2,b),(5,t)]
def func(a,b):
# do something for a and b
return (c,d)
output = []
for x, y in tups:
output.append(func(x,y))
output will be
[(c,d),(m,n),(h,j)]
I think map is more suitable for your use case
tups = [(1,"a"),(2,"b"),(5,"t")]
def func(z):
# some random operation say interchanging elements
x, y = z
return y, x
tups_new = list(map(func, tups))
print(tups_new)
Output:
[('a', 1), ('b', 2), ('t', 5)]
just write your loop in func:
tups = [(1,a),(2,b),(5,t)]
def func(tuples):
for a, b in tuples:
# do something for a and b
result.append((c,d))
return result
output = []
output.append(func(tups))
Just do this with list comprehensions:
tups = [(1,"a"),(2,"b"),(5,"t")]
print([(obj[1], obj[0]) for obj in tups])
# [('a', 1), ('b', 2), ('t', 5)]

How to iterate over each pair of items in a dictionary

I'm making a gravity simulator and I need to calculate the resultant force acting upon each body.
In order to do this, I need to iterate through every pair of bodies in a dictionary (id: instance of Body class) and get the gravitational force between those two bodies. Then, I would add up all the forces and get the resultants.
But, how do I iterate over each pair of items in a dictionary only once in Python? If the celestial bodies were kept in a list, it would be simple:
for i in range(len(bodies)):
for j in range(len(bodies) - i - 1):
k = j - i + 1
b1 = bodies[i]
b2 = bodies[k]
values() and itertools' combinations are ideal for this use case.
from itertools import combinations
for a, b in combinations(bodies.values(), 2):
print a, b
you're looking for itertools.combinations():
An example:
In [76]: lis=['a','b','c','d'] #consider these as your dictionary items
In [77]: [x for x in combinations(lis,2)]
Out[77]: [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
The itertools module provides an excellent combinations method you could use:
from itertools import combinations
bodies = {}
# add bodies
for a,b in combinations(bodies.values(), 2):
# a and b are a pair of bodies. do stuff
pass
Incidentally, this will still work even if you use a list:
from itertools import combinations
bodies = []
# add bodies
for a,b in combinations(bodies, 2):
pass

Python - Arranging combinations of list into a list of tuples of various sizes

I have a list of strings:
l = ['a', 'b', 'c']
I want to create all possible combinations of the list elements in groups of different sizes. I would prefer this to be a list of tuples of tuples, but it could also be a list of lists of lists, etc. The orders of the tuples, and of the tuples in the tuples, does not matter. No list element can be repeated in either the tuples or the tuples of tuples. For the above list, I would expect something like:
[(('a'),('b'),('c')),
(('a', 'b'), ('c')),
(('a', 'c'), ('b')),
(('b', 'c'), ('a')),
(('a', 'b', 'c'))]
Any help is greatly appreciated.
EDIT:
I do require that each of the tuples in the list contain all of the elements of l.
senderle and Antimony, you are both correct regarding the omissions.
Here's one way to do things. I don't know if there are any more elegant methods. The itertools module has functions for combinations and permutations, but unfortunately, nothing for partitions.
Edit: My first version isn't correct, but fortunately, I already have this lying around from an old project I did.
You can also get a unique integer key that represents an edge bitset associated with each partition by returning d instead of d.values(). This is useful for efficiently testing whether one partition is a refinement of another.
def connectivityDictSub(num, d, setl, key, i):
if i >= num:
assert(key not in d)
d[key] = setl
else:
for ni in range(len(setl)):
nsetl, nkey = setl[:], key
for other in nsetl[ni]:
assert(other != i)
x,y = sorted((i, other))
ki = ((2*num-3-x)*x)/2 + y-1
nkey |= 1<<ki
nsetl[ni] = nsetl[ni] + [i] #not the same as += since it makes a copy
connectivityDictSub(num, d, nsetl, nkey, i+1)
nsetl = setl + [[i]]
connectivityDictSub(num, d, nsetl, key, i+1)
def connectivityDict(groundSet):
gset = sorted(set(groundSet))
d = {}
connectivityDictSub(len(gset), d, [], 0, 0)
for setl in d.values():
setl[:] = [tuple(gset[i] for i in x) for x in setl]
return map(tuple, d.values())
for x in connectivityDict('ABCD'):
print x
itertools should do most of the job you want.
Example:
stuff = [1, 2, 3]
for L in range(0, len(stuff)+1):
for subset in itertools.combinations(stuff, L):
print(subset)
The example is just to show itertools. You will have to figure it out to get the exact output you want.

What would be a better implementation of all combinations in lexicographic order of a jagged list?

I was put in a position today in which I needed to enumerate all possible combinations of jagged list. For instance, a naive approach would be:
for a in [1,2,3]:
for b in [4,5,6,7,8,9]:
for c in [1,2]:
yield (a,b,c)
This is functional, but not general in terms of the number of lists that can be used. Here is a more generalized approach:
from numpy import zeros, array, nonzero, max
make_subset = lambda x,y: [x[i][j] for i,j in enumerate(y)]
def combinations(items):
num_items = [len(i) - 1 for i in items]
state = zeros(len(items), dtype=int)
finished = array(num_items, dtype=int)
yield grab_items(items, state)
while True:
if state[-1] != num_items[-1]:
state[-1] += 1
yield make_subset(items, state)
else:
incrementable = nonzero(state != finished)[0]
if not len(incrementable):
raise StopIteration
rightmost = max(incrementable)
state[rightmost] += 1
state[rightmost+1:] = 0
yield make_subset(items, state)
Any recommendations on a better approach or reasons against the above approach?
The naive approach can be written more compactly as a generator expression:
((a,b,c) for a in [1,2,3] for b in [4,5,6,7,8,9] for c in [1,2])
The general approach can be written much more simply using a recursive function:
def combinations(*seqs):
if not seqs: return (item for item in ())
first, rest = seqs[0], seqs[1:]
if not rest: return ((item,) for item in first)
return ((item,) + items for item in first for items in combinations(*rest))
Sample usage:
>>> for pair in combinations('abc', [1,2,3]):
... print pair
...
('a', 1)
('a', 2)
('a', 3)
('b', 1)
('b', 2)
('b', 3)
('c', 1)
('c', 2)
('c', 3)

Categories