Related
This question already has answers here:
Pythonic way of checking if a condition holds for any element of a list
(3 answers)
Apply function to each element of a list
(4 answers)
Closed 9 months ago.
Hello guys I have list like A
max_x=4
min_x=0
A=[[(0, 1), (1, 0), (1, 1), (2, 0)], [(0, 3), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2)]]
A, includes different group of points (x,y) format.I wanted to find group if includes my max and min same time.Output should be like B.Because this cluster includes 0 and 4 as x.
B= [(0, 3), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2)]
Thank you.
You could use a list comprehension to find any sublists of A that have a tuple that has x == min_x and also a tuple that has x == max_x:
max_x=4
min_x=0
A=[[(0, 1), (1, 0), (1, 1), (2, 0)], [(0, 3), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2)]]
B = [l for l in A if any(x == min_x for x,_ in l) and any(x == max_x for x,_ in l)]
Output:
[[(0, 3), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2)]]
Here's a snippet with a regular itertools.product usage:
from itertools import product
arr = [1,2,3]
pairs = list(product(arr, arr))
# pairs = [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
Now I would like to have these points yielded in an order which can be achieved by sorting the resulting tuples in the following way:
sorted(pairs, key=lambda y:max(y))
# [(1, 1), (1, 2), (2, 1), (2, 2), (1, 3), (2, 3), (3, 1), (3, 2), (3, 3)]
Is there a way for me to input those numbers to itertools.product so it yields the tuples in this order, or do I need to sort the pairs after iterating over the results of itertools.product?
You can probably use your own modified approach to achieve this in one go.
sorted([(x, y) for x in [1, 2, 3] for y in [1, 2, 3]], key=lambda y:max(y))
OUTPUT
[(1, 1), (1, 2), (2, 1), (2, 2), (1, 3), (2, 3), (3, 1), (3, 2), (3, 3)]
I want to find possible paths on a finite grid of points. Say, starting point is (x,y). Then next point (m,n) in the path is given by conditions
(m!=x) and (n!=y) ie. I exclude the row and column I was in previously.
n < y ie. I always hop DOWN.
m,n >= 0 ie. all the points are always in first quadrant
Stopping criteria is when a point lies on x axis.
Hence, generate all possible combinations of such 'paths' possible.
Following is what I've tried.
def lisy(x,y):
return [(i,j) for i in range(4,0,-1) for j in range(4,0,-1) if(i!=x and j<y)]
def recurse(x,y):
if (not lisy(x,y)):
return (x,y)
else:
return [(x,y), [recurse(i,j) for i,j in lisy(x,y)]]
OUTPUT:
In [89]: recurse(1,4)
Out[89]:
[(1, 4),
[[(4, 3),
[[(3, 2), [(4, 1), (2, 1), (1, 1)]],
(3, 1),
[(2, 2), [(4, 1), (3, 1), (1, 1)]],
(2, 1),
[(1, 2), [(4, 1), (3, 1), (2, 1)]],
(1, 1)]],
[(4, 2), [(3, 1), (2, 1), (1, 1)]],
(4, 1),
[(3, 3),
[[(4, 2), [(3, 1), (2, 1), (1, 1)]],
(4, 1),
[(2, 2), [(4, 1), (3, 1), (1, 1)]],
(2, 1),
[(1, 2), [(4, 1), (3, 1), (2, 1)]],
(1, 1)]],
[(3, 2), [(4, 1), (2, 1), (1, 1)]],
(3, 1),
[(2, 3),
[[(4, 2), [(3, 1), (2, 1), (1, 1)]],
(4, 1),
[(3, 2), [(4, 1), (2, 1), (1, 1)]],
(3, 1),
[(1, 2), [(4, 1), (3, 1), (2, 1)]],
(1, 1)]],
[(2, 2), [(4, 1), (3, 1), (1, 1)]],
(2, 1)]]
This gives me a nested lists of possible new points from each point.
Can anyone tell me how to process my list obtained from recurse(1,4)?
edit1:
Effectively I hop from a given starting point (in a 4x4 grid [finite]), satisfying the three conditions mentioned until stopping criteria is met, ie. m,n > 0
I clarify the requirements I am working under in the docstring of my generator gridpaths(). Note that I have the horizontal size of the grid as a global variable and the vertical size of the grid is irrelevant, the x-coordinates of path points can be up to but not exceed that global value, and x-coordinates of non-consecutive path points can be equal (though consecutive path points must have different x-coordinates). I changed the name of the routine but kept the arguments as you had them. This version of my code adds the requirement that the y-coordinate of the final point on the path must be 1, and it also is safer in accepting arguments.
This is a generator of lists, so my test code shows how large the generator is then prints all the lists.
def gridpaths(x, y):
"""Generate all paths starting at (x,y) [x and y must be positive
integers] where, if (m,n) is the next point in the path after
(x,y), then m and n are positive integers, m <= xsize [xsize is a
global variable], m != x, and n < y, and so on for all consecutive
path points. The final point in the path must have a y-coordinate
of 1. Paths are yielded in lexicographic order."""
def allgridpaths(x, y, pathsofar):
"""Generate all such paths continuing from pathssofar without
the y == 1 requirement for the final path point."""
newpath = pathsofar + [(x, y)]
yield newpath
for m in range(1, xsize+1):
if m != x:
for n in range(1, y):
for path in allgridpaths(m, n, newpath):
yield path
x, y = max(int(x), 1), max(int(y), 1) # force positive integers
for path in allgridpaths(x, y, []):
# Only yield paths that end at y == 1
if path[-1][1] == 1:
yield path
# global variable: horizontal size of grid
xsize = 4
print(sum(1 for p in gridpaths(1, 4)), 'paths total.')
for p in gridpaths(1, 4):
print(p)
The printout shows that the point (1,4) in a 4x4 grid yields 48 paths. In fact, gridpaths(x, y) will return (xsize - 1) * xsize ** (y - 2) paths, which can grow very quickly. That is why I programmed a generator of lists rather than a list of lists. Let me know if your requirements are different from what I suppose. The printout from that code above is:
48 paths total.
[(1, 4), (2, 1)]
[(1, 4), (2, 2), (1, 1)]
[(1, 4), (2, 2), (3, 1)]
[(1, 4), (2, 2), (4, 1)]
[(1, 4), (2, 3), (1, 1)]
[(1, 4), (2, 3), (1, 2), (2, 1)]
[(1, 4), (2, 3), (1, 2), (3, 1)]
[(1, 4), (2, 3), (1, 2), (4, 1)]
[(1, 4), (2, 3), (3, 1)]
[(1, 4), (2, 3), (3, 2), (1, 1)]
[(1, 4), (2, 3), (3, 2), (2, 1)]
[(1, 4), (2, 3), (3, 2), (4, 1)]
[(1, 4), (2, 3), (4, 1)]
[(1, 4), (2, 3), (4, 2), (1, 1)]
[(1, 4), (2, 3), (4, 2), (2, 1)]
[(1, 4), (2, 3), (4, 2), (3, 1)]
[(1, 4), (3, 1)]
[(1, 4), (3, 2), (1, 1)]
[(1, 4), (3, 2), (2, 1)]
[(1, 4), (3, 2), (4, 1)]
[(1, 4), (3, 3), (1, 1)]
[(1, 4), (3, 3), (1, 2), (2, 1)]
[(1, 4), (3, 3), (1, 2), (3, 1)]
[(1, 4), (3, 3), (1, 2), (4, 1)]
[(1, 4), (3, 3), (2, 1)]
[(1, 4), (3, 3), (2, 2), (1, 1)]
[(1, 4), (3, 3), (2, 2), (3, 1)]
[(1, 4), (3, 3), (2, 2), (4, 1)]
[(1, 4), (3, 3), (4, 1)]
[(1, 4), (3, 3), (4, 2), (1, 1)]
[(1, 4), (3, 3), (4, 2), (2, 1)]
[(1, 4), (3, 3), (4, 2), (3, 1)]
[(1, 4), (4, 1)]
[(1, 4), (4, 2), (1, 1)]
[(1, 4), (4, 2), (2, 1)]
[(1, 4), (4, 2), (3, 1)]
[(1, 4), (4, 3), (1, 1)]
[(1, 4), (4, 3), (1, 2), (2, 1)]
[(1, 4), (4, 3), (1, 2), (3, 1)]
[(1, 4), (4, 3), (1, 2), (4, 1)]
[(1, 4), (4, 3), (2, 1)]
[(1, 4), (4, 3), (2, 2), (1, 1)]
[(1, 4), (4, 3), (2, 2), (3, 1)]
[(1, 4), (4, 3), (2, 2), (4, 1)]
[(1, 4), (4, 3), (3, 1)]
[(1, 4), (4, 3), (3, 2), (1, 1)]
[(1, 4), (4, 3), (3, 2), (2, 1)]
[(1, 4), (4, 3), (3, 2), (4, 1)]
My input files have lines that looks like this:
[(0, 1), (1, 3), (2, 1), (3, 1), (4, 1)]
[(0, 1, 6), (1, 3,7), (3, 1,4), (3, 1,3), (8, 1,2)]
[1,2,3,5,3]
There are no letters, no decimals, only integers and number of element in tuples will be consistent.
How do i make them into real list of tuples / list of int?
Python comes with batteries included - that problem is solved by ast.literal_eval():
>>> import ast
>>> ast.literal_eval("[(0, 1), (1, 3), (2, 1), (3, 1), (4, 1)]")
[(0, 1), (1, 3), (2, 1), (3, 1), (4, 1)]
>>> ast.literal_eval("[(0, 1, 6), (1, 3,7), (3, 1,4), (3, 1,3), (8, 1,2)]")
[(0, 1, 6), (1, 3, 7), (3, 1, 4), (3, 1, 3), (8, 1, 2)]
>>> ast.literal_eval("[1,2,3,5,3]")
[1, 2, 3, 5, 3]
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