I have this input P (0, 2,+1) (2, 0, -1) (0, 4,+1) (4, 0, -1) and I would like to have it printed out this way [(0, 2, 1), (2, 0, -1), (0, 4, 1), (4, 0, -1)]
. However, due to the extra space in the input I ran into this error. Without making any change to the input, I wonder if anyone could advise? Thanks
algorithm_type_2 = list(eval(user_input_2))
File "<string>", line 1
(0,,2,+1),(2,,0,,-1),(0,,4,+1),(4,,0,,-1)
^
SyntaxError: invalid syntax
user_input = input().split()
# input_list = user_input.split()
# algorithm_type = 'X'
algorithm_type = user_input.pop(0)
user_input_2 = ','.join(user_input)
algorithm_type_2 = list(eval(user_input_2))
print(user_input_2)
print(algorithm_type_2)
I'm not sure the context etc.. I know this is ugly, but in situations like this you can add a split character just to have a nice easy character to split on. Did I say split?
Here is what I did. Replace the closing bracket with a closing bracket and a "$" then split on the "$".
user_input = input().replace(")",")$").split("$")
# input_list = user_input.split()
# algorithm_type = 'X'
algorithm_type = user_input.pop(0)
user_input_2 = ','.join(user_input)
algorithm_type_2 = list(eval(user_input_2))
print(user_input_2)
print(algorithm_type_2)
This gave me the output you wanted.
= RESTART: C:/Users/Jeremy Wright/Desktop/Desktop Mess/Not Work/StackOverflow Stuff/example.py
(0, 2,+1) (2, 0, -1) (0, 4,+1) (4, 0, -1)
(2, 0, -1), (0, 4,+1), (4, 0, -1),
[(2, 0, -1), (0, 4, 1), (4, 0, -1)]
>>>
Related
This question already has answers here:
python order of elements in set
(2 answers)
Does Python have an ordered set?
(15 answers)
Closed 3 months ago.
I face a strange problem where set comprehension won't work as intended.
b=[[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
print({(R, 0, 0) for _, R, _ in b})
We have output
{(12, 0, 0), (9, 0, 0), (7, 0, 0), (20, 0, 0), (24, 0, 0)}
Not the desired answer
{(9, 0, 0), (7, 0, 0), (12, 0, 0), (20, 0, 0), (24, 0, 0)}
What went wrong? For list comprehension, it works fine.
b=[[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
print([(R, 0, 0) for _, R, _ in b])
We have output
[(9, 0, 0), (7, 0, 0), (12, 0, 0), (20, 0, 0), (24, 0, 0)]
It is natural to have sets comprehension looks like this. Based on Iain and juanpa's comment, sets are not ordered. The order is not preserved. So that's why we have "unintended" print value.
On the other hand, if you want to preserve the order, you should use lists.
I´m trying to iterate trough elements where list N return an iterator, which goes through all possible tuples A, where Ai changes from 0 to Ni. the elements are always and int. A solution or a path to a solution with for loops and while loops is preferred.
def f(*args):
lst = []
for i in range(args[0]):
for x in range(args[1]):
for a in range(args[2]):
for v in range(args[3]):
lst.append((i,x,a,v))
return lst
print(f(5, 3, 1, 5))
This code works, but I don't want it hard coded: let's say if I want to input another int, lets say: print(f(5, 3, 1, 5, 6)) <- it should work for that as well.
So the question is how to make a loop like the one above without the hard coding?
I have tried to use a while loop and a for loop inside the while:
def f(*args):
cnt = 0
lst = []
while len(args) > cnt:
print(cnt)
for i in range(args[cnt]):
lst.append(i)
print(lst)
cnt += 1
return lst
print(f(5, 3, 1, 5))
this is the correct output of the first code snippet and this is what I want without the hard coding:
Another way you could do it is:
def f(*args):
res = [[]]
for z in map(range, args):
res = [tuple(x)+(y,) for x in res for y in z]
return res
f(5,3,1,5)
You can use recursion for this. It replaces the unknown number of layered for loops.
def fr(tt, idx = 0):
lst = []
if idx == len(tt)-1: # last index, just loop
for x in range(tt[idx]):
lst.append(tt[:-1] + (x,))
return lst
for x in range(tt[idx]): # loop and call child loops
l2 = tt[:idx] + (x,) + tt[idx+1:] # update this index
lst.extend(fr(tuple(l2), idx+1)) # iterate next level
return lst
print(fr((5, 3, 1, 5)))
print(fr((5, 3, 1, 5, 6)))
Output
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3), (0, 0, 0, 4), ......., (4, 2, 0, 3), (4, 2, 0, 4)]
[(0, 0, 0, 0, 0), (0, 0, 0, 0, 1), (0, 0, 0, 0, 2), (0, 0, 0, 0, 3), ......., (4, 2, 0, 4, 4), (4, 2, 0, 4, 5)]
I've the following graph,
ed_ls = [(0, 1), (0, 63), (1, 2), (1, 3), (54, 0)]
ed_w = [1, 2, 3, 4, 5]
G = nx.Graph()
G.add_edges_from(ed_ls)
edge_w = OrderedDict(zip(G.edges, ed_w))
nx.set_edge_attributes(G, edge_w, 'weight')
print(G.edges)
print(nx.get_edge_attributes(G, 'weight'))
Output obtained:
{(0, 1): 1, (0, 63): 2, (0, 54): 3, (1, 2): 4, (1, 3): 5}
The edge weights in ed_w are in the same order of edges in ed_ls. Since the order of edges
is not preserved, wrong edge weights are assigned. I could use nx.DiGraph to avoid this problem. However, I want to use nx.k_core later on and this doesn't work on directed graphs. Suggestions on
how to go ahead will be highly appreciated.
You can simplify this by using Graph.add_weighted_edges_from:
ed_ls = [(0, 1), (0, 63), (1, 2), (1, 3), (54, 0)]
ed_w = [1, 2, 3, 4, 5]
G = nx.Graph()
G.add_weighted_edges_from(((*edge, w) for edge, w in zip(ed_ls, ed_w)))
G.edges(data=True)
EdgeDataView([(0, 1, {'weight': 1}), (0, 63, {'weight': 2}),
(0, 54, {'weight': 5}), (1, 2, {'weight': 3}),
(1, 3, {'weight': 4})])
If you're using a python version above 3.7, dictionaries maintain insertion order, but the order you seen when printing G.edges(data=True) is not necessarily the order in which edges where added, it rather agrees with node adding. As you can see in this example (54, 0) is shown before
(1, 2) since node 0 was added before.
Why dont you assign the weights to the edges at the time of adding them to the graph?
ed_ls = [(0, 1), (0, 63), (1, 2), (1, 3), (54, 0)]
ed_w = [1, 2, 3, 4, 5]
G = nx.Graph()
for i in range(len(ed_ls)):
src, dst = ed_ls[i]
G.add_edge(src, dst, weight=ed_w[i])
I wanted to find a better way to loop through orthodiagonal indices in order, I am currently using numpy but I think I'm making an unnecessary number of function calls.
import numpy as np
len_x, len_y = 50, 50 #they don't have to equal
index_arr = np.add.outer(np.arange(len_x), np.arange(len_y))
Currently, I am looping through like this:
for i in range(np.max(index_arr)):
orthodiag_indices = zip(*np.where(index_arr == i))
for index in orthodiag_indices:
# DO FUNCTION OF index #
I have an arbitrary function of the index tuple, index and other parameters outside of this loop. It feels like I don't need the second for loop, and I should be able to do the whole thing in one loop. On top of this, I'm making a lot of function calls from zip(*np.where(index_arr == i)) for every i. What's the most efficient way to do this?
Edit: should mention that it's important that the function applies to index_arr == i in order, i.e., it does 0 first, then 1, then 2 etc. (the order of the second loop doesn't matter).
Edit 2: I guess what I want is a way to get the indices [(0,0), (0,1), (1,0), (2,0), (1,1), (2,0), ...] efficiently. I don't think I can apply a vectorized function because I am populating an np.zeros((len_x, len_y)) array, and going back to the first edit, the order matters.
You could use tril/triu_indices. Since the order of the (former) inner loop doesn't matter dimensions can be swapped as needed, I'll assume L>=S:
L,S = 4,3
a0,a1 = np.tril_indices(L,0,S)
b0,b1 = np.triu_indices(S,1)
C0 = np.concatenate([a0-a1,b0+L-b1])
C1 = np.concatenate([a1,b1])
*zip(C0,C1),
# ((0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (3, 0), (2, 1), (1, 2), (3, 1), (2, 2), (3, 2))
I think itertools.product() will be of use here
import itertools as it
x,y = 2,3
a=list(it.product(range(x),range(y))
which gives a as
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]
If you need them in order then,
b=np.argsort(np.sum(a,1))
np.array(a)[b]
which gives,
array([[0, 0],
[0, 1],
[1, 0],
[0, 2],
[1, 1],
[1, 2]])
Hope that helps!
In Python is there a way to get all 3 pairs or n pairs of a list from a list?
For example list = [1,2,3,4]
result : [[1,2,3],[2,3,4],[1,2,4]]
I want to find all possible n pairs of lists from a Python list. I do not want to import any other functions like itertools.
You can use the module itertools. It comes inside Python by default (you don't need to install it throught third party modules):
>>> import itertools
>>> print(itertools.permutations([1,2,3,4], 3))
[(1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 3, 4), (1, 4, 2), (1, 4, 3), (2, 1, 3), (2, 1, 4), (2, 3, 1), (2, 3, 4), (2, 4, 1), (2, 4, 3), (3, 1, 2), (3, 1, 4), (3, 2, 1), (3, 2, 4), (3, 4, 1), (3, 4, 2), (4, 1, 2), (4, 1, 3), (4, 2, 1), (4, 2, 3), (4, 3, 1), (4, 3, 2)]
This itertools.permutations(iterable, r=None) produces all the possible permutations of a given iterable element (like a list). If r is not specified or is None, then r defaults to the length of the iterable and all possible full-length permutations are generated.
If you are looking only for n pair of permutations instead of all the possible permutations just delete the rest of them:
>>> print(list(itertools.permutations([1,2,3,4], 3))[:3])
[(1, 2, 3), (1, 2, 4), (1, 3, 2)]
As you asked in comments you can do that without importing any module. itertools.permutations is just a function, which you can make by yourself:
def permutations(iterable, r=None):
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
if r > n:
return
indices = list(range(n))
cycles = list(range(n, n-r, -1))
yield tuple(pool[i] for i in indices[:r])
while n:
for i in reversed(range(r)):
cycles[i] -= 1
if cycles[i] == 0:
indices[i:] = indices[i+1:] + indices[i:i+1]
cycles[i] = n - i
else:
j = cycles[i]
indices[i], indices[-j] = indices[-j], indices[i]
yield tuple(pool[i] for i in indices[:r])
break
else:
return
But I strongly advise your importing it. If you don't want to import the whole module, just this function simply do from itertools import permutations.