Itertools product return sets [duplicate] - python

This question already has answers here:
Cartesian products of lists without duplicates
(2 answers)
Closed 3 years ago.
I want to create an iterator with cartesian products where no duplicates are present in the sense of sets.
import itertools
A = list(range(1,10))
iterator = itertools.product(A,repeat=2)
print(list(iterator))
>> [(1,1),(1,2),...,(2,1),...,(9,9)]
Above is wrong in the sense that set((1,2)) == set((2,1)). I could do
B = list()
for i in iterator:
if all(set(i) != set(j) for j in B):
B.append(i)
and get a list of the wanted output, but I would like to stay away from lists since I run into memory problems when scaling the repeat-option.
Can anyone help me out?

A = list(range(1,10))
k = []
for i, v in enumerate(A):
for _, v1 in enumerate(A[i:]):
k.append((v, v1))
print(k)
Output is
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (4, 4), (4, 5), (4, 6), (4, 7), (4, 8), (4, 9), (5, 5), (5, 6), (5, 7), (5, 8), (5, 9), (6, 6), (6, 7), (6, 8), (6, 9), (7, 7), (7, 8), (7, 9), (8, 8), (8, 9), (9, 9)]

Related

How to sort edges of path based on start and end point?

I have a problem with the path of each truck. From my model, I get the output of each truck path is misorder. I would like to order my list of edges based on the start and endpoint.
trucks = {0: (10, 1),1:(7,1),2: (3, 10),3:(7,4)} # truck_number:(start_point, end_point)
input I need to change:
path = {0: [(2, 1), (5, 2), (6, 5), (10, 6)],
1: [(2, 1), (5, 2), (6, 5), (7, 6)],
2: [(2, 5), (3, 2), (5, 6), (6, 10)],
3: [(5, 4), (6, 5), (7, 6)]}
output I need
output_i_need ={0: [(10, 6), (6, 5), (5, 2), (2, 1)],
1: [(7, 6), (6, 5), (5, 2), (2, 1)],
2: [(3, 2), (2, 5), (5, 6), (6, 10)],
3: [(7, 6), (6, 5), (5, 4)]}
is there any library in python to order my list of edges?
I don't know of a library, but writing a function to reorder the list of edges is easy if you convert the list of edges into a dictionary mapping edge_start to edge_end.
trucks = {0: (10, 1),1:(7,1),2: (3, 10),3:(7,4)} # truck_number:(start_point, end_point)
paths = {0: [(2, 1), (5, 2), (6, 5), (10, 6)],
1: [(2, 1), (5, 2), (6, 5), (7, 6)],
2: [(2, 5), (3, 2), (5, 6), (6, 10)],
3: [(5, 4), (6, 5), (7, 6)]}
def reordered(l, start, end):
d = dict(l)
result = []
while start != end:
result.append((start, d[start]))
start = d[start]
return result
new_paths = { truck: reordered(path, trucks[truck][0], trucks[truck][1])
for truck,path in paths.items() }
print(new_paths)
# {0: [(10, 6), (6, 5), (5, 2), (2, 1)],
# 1: [(7, 6), (6, 5), (5, 2), (2, 1)],
# 2: [(3, 2), (2, 5), (5, 6), (6, 10)],
# 3: [(7, 6), (6, 5), (5, 4)]}

Unpack list of lists into list [duplicate]

This question already has answers here:
How do I make a flat list out of a list of lists?
(34 answers)
Closed 4 years ago.
I have list of lists of tuples:
a = [[(1, 2), (3, 4), (5, 6)], [(7, 8), (9, 10)]]
How can I make one list of tuples:
b = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
Naive way is:
b = []
for c in a:
for t in c:
b.append(t)
List comprehension or any other ideas are welcome.
Using itertools
demo:
import itertools
a = [[(1, 2), (3, 4), (5, 6)], [(7, 8), (9, 10)]]
print(list(itertools.chain(*a)))
Output:
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
This operation is called 'flatten' in some of other languages.
In python, followings method might be shortest.
a = [[(1, 2), (3, 4), (5, 6)], [(7, 8), (9, 10)]]
sum(a, [])
// [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
It also work in the case the parent list have many child lists.
b = [[1],[2],[3],[4],[5]]
sum(b, [])
// [1, 2, 3, 4, 5]
You don't want to append, you want to extend. You can use the really simple loop
a = [[(1, 2), (3, 4), (5, 6)], [(7, 8), (9, 10)]]
single_level_list = []
for lst in a:
single_level_list.extend(lst)
print(single_level_list)
>>> [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]

Checking if the numbers in a list in a list are in a certain range

So I have a list with multiple list in it which represent something like coordinates. In my case they are positions on a chessboard.
The list would look something like this:
[(3, 3), (4, 3), (5, 3), (6, 3), (3, 4), (4, 4), (5, 4), (6, 4), (3, 5), (4, 5)]
This is just an example.
My problem is, I need to check if any of these coordiantes are out of a certain range, on the chessboard, for example 1-8. Unfortunately i could only get the all() command to work with a list which just consists of numbers and not a list with lists of numbers.
Then iterate through each of the individual coordinates:
>>> coords = [(3, 3), (4, 3), (5, 3), (6, 3), (3, 4), (4, 4), (5, 4), (6, 4), (3, 5), (4, 5)]
>>> all(1 <= c <= 8 for coord in coords for c in coord)
True
Let's try two cases where there is a coordinate out of range:
>>> coords = [(3, 3), (4, 3), (5, 3), (6, 3), (3, 4), (0, 5), (4, 4), (5, 4), (6, 4), (3, 5), (4, 5)]
>>> all(1 <= c <= 8 for coord in coords for c in coord)
False
>>> coords = [(3, 3), (4, 3), (5, 3), (6, 3), (4, 88), (3, 4), (4, 4), (5, 4), (6, 4), (3, 5), (4, 5)]
>>> all(1 <= c <= 8 for coord in coords for c in coord)
False
you can import numpy module and use function max
import numpy as np
>>> l =np.array([(3, 3), (4, 3), (5, 3), (6, 3), (3, 4), (4, 4), (5, 4), (6, 4), (3, 5), (4, 5)])
>>> l.max()
6

Generating pairs from python list

I'm trying generate a bunch of pairs from a list in python --- I figured out a way of doing it using for loops:
keys = range(10)
keypairs = list()
for i in range(len(keys)):
for j in range(i+1, len(keys)):
keypairs = keypairs + [(keys[i], keys[j])]
Is there a more "python style" way of doing this? My method doesn't seem very elegant ...
You want two range loops, one from 0 to n and the inner from each i of the first range + 1 to n using a list comp:
n = 10
pairs = [(i, j) for i in range(n) for j in range(i+1, n)]
from pprint import pprint as pp
pp(pairs,compact=True)
[(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (1, 2),
(1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (2, 3), (2, 4), (2, 5),
(2, 6), (2, 7), (2, 8), (2, 9), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9),
(4, 5), (4, 6), (4, 7), (4, 8), (4, 9), (5, 6), (5, 7), (5, 8), (5, 9), (6, 7),
(6, 8), (6, 9), (7, 8), (7, 9), (8, 9)]
Which exactly matches your output.
You want to check list comprehension:
sorted([(i, j) for j in range(10) for i in range(10) if j > i])
I would use itertools for that. Check combinations_with_replacement and combinations methods.
And here is the code sample:
import itertools
list(itertools.combinations(keys, 2))
EDITED: Yes, I noticed that it should be combinations, not combinations_with_replacements.

Making Combinations (Python)

In Python, is there a better way to get the set of combinations of n elements from a k-element set than nested for loops or list comprehensions?
For example, say from the set [1,2,3,4,5,6] I want to get [(1,2),(1,3),(1,4),(1,5),(1,6),(2,3),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6),(4,5),(4,6),(5,6)]. Is there a better of of making it than
nums=[1,2,3,4,5,6]
doubles=[]
for a in nums:
for b in nums[a+1:]
doubles.append((a,b))
? It's okay if the elements of the list we end up with are sets, tuples, or lists; I just feel there should be an easier way to do this.
You can use itertools.combinations:
>>> from itertools import combinations
>>> nums = [1,2,3,4,5,6]
>>> list(combinations(nums, 2))
[(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6), (4, 5), (4, 6), (5, 6)]
The itertools module has a lot of really powerful tools that can be used in situations like this. In this case, you want itertools.combinations. Some other ones that you might find useful are itertools.combinations_with_replacement and itertools.permutations.
Example:
>>> import itertools
>>> list(itertools.combinations(range(1,7),2))
[(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6), (4, 5), (4, 6), (5, 6)]
>>> list(itertools.combinations_with_replacement(range(1,7),2))
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (3, 3), (3, 4), (3, 5), (3, 6), (4, 4), (4, 5), (4, 6), (5, 5), (5, 6), (6, 6)]
>>> list(itertools.permutations(range(1,7),2))
[(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 3), (2, 4), (2, 5), (2, 6), (3, 1), (3, 2), (3, 4), (3, 5), (3, 6), (4, 1), (4, 2), (4, 3), (4, 5), (4, 6), (5, 1), (5, 2), (5, 3), (5, 4), (5, 6), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5)]
You could use the itertools module
import itertools
alphabet = ['1','2','3','4','5','6']
combos = list(itertools.combinations(alphabet, 2))
print combos

Categories

Resources