I am trying to save the result of a nested for loop in a list in python. can someone tell me how to do it?
V is an array containing [1, 2, 3]
while n is the length = 3
and sq is the matrix containing swaps.
i have tried many approaches but whenever i return the result it only gives me one element of the list.
any help would be appreciated. Thankyou
def Permute1(sq,v,n):
for i in range(n):
for j in range(n):
if (sq[i,j]==1):
temp=v[i]
v[i]=v[j]
v[j]=temp
print(v)
results:
[1, 2, 3]
[2, 1, 3]
[3, 1, 2]
[3, 1, 2]
[3, 2, 1]
[3, 2, 1]
I'm not sure what is the utility of d = vhere.
To swap two elements in Python, I recommend:
v[i], v[j] = v[j], v[i]
Declaring an empty list before for loops and append the values (like AkshayNevrekar said) can also be useful, depending on what you need as a result.
def Permute1(sq,v,n):
result=[]
for i in range(n):
for j in range(n):
if (sq[i,j]==1):
temp=v[i]
v[i]=v[j]
v[j]=temp
result += [v]
print(result)
return result
No tested but may be it can help.
Check yield.
You can use this to generate all the permutations and process each one of them & store them in a list.
Related
Suppose I have an array A of size N and want to perform Q queries and each query is the type -
"X L R" where X is an element that I want to add in array A from location L to R.
Mathematical format like-
N=5
A=[1 4 3 2 4]
Q=2
X L R=[[5 1 2],
[-5 1 3]]
my algorithm for this problem is like this-
#python code
N=int(input())
A=list(map(int,input().split()))
Q=int(input())
L=[list(map(int,input().split())) for i in range(Q)]
for i in range(Q):
for j in range(L[i][1]-1,L[i][2]):
A[j]=A[j]+L[i][0]
but my code takes a long time hence I want to reduce the time of this code.
How I can reduce the time of this code anyone has any idea please let me know.
Thank you.
What you basically need is a difference array. That would allow you to get Q update queries done in O(1) time each, plus O(N) complexity to recreate the original array.
n = 5
a = [1, 4, 3, 2, 4]
q = 2
xlr = [[5, 1, 2], [-5, 1, 3]]
for item in xlr:
# create the list to be inserted first
to_add = [item[0]]*(item[2]-item[1])
a[item[1]:item[1]] = to_add
print(a)
Inside the for loop, I first create the list that needs to be inserted at the desired location. After that, I set the list that needs to be inserted at the position identified by the element xlr[i][1].
Generated output - [1, -5, -5, 5, 4, 3, 2, 4]
Let's say I have a list of lists, for example:
[[0, 2], [0, 1], [2, 3], [4, 5, 7, 8], [6, 4]]
and if at least one of the values on a list is the same that another one of a different list, i would like to unite the lists so in the example the final result would be:
[[0, 1, 2, 3], [4, 5, 6, 7, 8]]
I really don't care about the order of the values inside the list [0, 1, 2, 3] or [0, 2, 1, 3].
I tried to do it but it doesn't work. So have you got any ideas? Thanks.
Edit(sorry for not posting the code that i tried before):
What i tried to do was the following:
for p in llista:
for q in p:
for k in llista:
if p==k:
llista.remove(k)
else:
for h in k:
if p!=k:
if q==h:
k.remove(h)
for t in k:
if t not in p:
p.append(t)
llista_final = [x for x in llista if x != []]
Where llista is the list of lists.
I have to admit this is a tricky problem. I'm really curious what does this problem represent and/or where did you find it out...
I initially have thought this is just a graph connected components problem, but I wanted to take a shortcut from creating an explicit representation of the graph, running bfs, etc...
The idea of the solution is this: for every sublist, check if it has some common element with any other sublist, and replace that with their union.
Not very pythonic, but here it is:
def merge(l):
l = list(map(tuple, l))
for i, h in enumerate(l):
sh = set(h)
for j, k in enumerate(l):
if i == j: continue
sk = set(k)
if sh & sk: # h and k have some element in common
l[j] = tuple(sh | sk)
return list(map(list, set(l)))
Here is a function that does what you want. I tried to use self-documenting variable names and comments to help you understand how this code works. As far as I can tell, the code is pythonic. I used sets to speed up and simplify some of the operations. The downside of that is that the items in your input list-of-lists must be hashable, but your example uses integers which works perfectly well.
def cliquesfromlistoflists(inputlistoflists):
"""Given a list of lists, return a new list of lists that unites
the old lists that have at least one element in common.
"""
listofdisjointsets = []
for inputlist in inputlistoflists:
# Update the list of disjoint sets using the current sublist
inputset = set(inputlist)
unionofsetsoverlappinginputset = inputset.copy()
listofdisjointsetsnotoverlappinginputset = []
for aset in listofdisjointsets:
# Unite set if overlaps the new input set, else just store it
if aset.isdisjoint(inputset):
listofdisjointsetsnotoverlappinginputset.append(aset)
else:
unionofsetsoverlappinginputset.update(aset)
listofdisjointsets = (listofdisjointsetsnotoverlappinginputset
+ [unionofsetsoverlappinginputset])
# Return the information in a list-of-lists format
return [list(aset) for aset in listofdisjointsets]
print(cliquesfromlistoflists([[0, 2], [0, 1], [2, 3], [4, 5, 7, 8], [6, 4]]))
# printout is [[0, 1, 2, 3], [4, 5, 6, 7, 8]]
This solution modifies the generic breadth-first search to gradually diminish the initial deque and update a result list with either a combination should a match be found or a list addition if no grouping is discovered:
from collections import deque
d = deque([[0,2] , [0,1] , [2,3] , [4,5,7,8] , [6,4]])
result = [d.popleft()]
while d:
v = d.popleft()
result = [list(set(i+v)) if any(c in i for c in v) else i for i in result] if any(any(c in i for c in v) for i in result) else result + [v]
Output:
[[0, 1, 2, 3], [8, 4, 5, 6, 7]]
I'm trying to do the following in python: given a list of lists and an integer i
input = [[1, 2, 3, 4], [1, 2, 3, 4], [5, 6, 7, 8]]
i = 1
I need to obtain another list which has all 1s for the elements of the i-th list, 0 otherwise
output = [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0]
I wrote this code
output = []
for sublist in range(0, len(input)):
for item in range(0, len(input[sublist])):
output.append(1 if sublist == i else 0)
and it obviously works, but since I'm a newbie in python I suppose there's a better 'pythonic' way of doing this.
I thought using map could work, but I can't get the index of the list with it.
Creating extra variable to get index of current element in interation is quite unpythonic. Usual alternative is usage of enumerate built-in function.
Return an enumerate object. sequence must be a sequence, an iterator,
or some other object which supports iteration. The next() method of
the iterator returned by enumerate() returns a tuple containing a
count (from start which defaults to 0) and the values obtained from
iterating over sequence.
You may use list comprehension with double loop inside it for concise one liner:
input_seq = [[1, 2, 3, 4], [1, 2, 3, 4], [5, 6, 7, 8]]
i = 1
o = [1 if idx == i else 0 for idx, l in enumerate(input_seq) for _ in l]
Alternatively,
o = [int(idx == i) for idx, l in enumerate(input_seq) for _ in l]
Underscore is just throwaway name, since in this case we don't care for actual values stored in input sublists.
Here's a 1-liner, but it's not really obvious:
output = [int(j == i) for j, sublist in enumerate(input) for _ in sublist]
Somewhat more obvious:
output = []
for j, sublist in enumerate(input):
output.extend([int(i == j)] * len(sublist))
Then "0 or 1?" is computed only once per sublist, which may or may not be more efficient.
I want to create what I thought was a fairly straightforward function. The function just runs through a list of lists and returns any list that does not have a 1 in all of the list elements following the second element ([2: ]). So given the list of lists [[1, 2, 1, 1, 1, 1], [4, 5, 1, 2, 0.3, 1, 1, 1]] the function would return [4, 5, 1, 2, 0.3, 1, 1, 1]. What I have so far is:
def discover(A):
"""Looks for list that has an element not equal to one.
"""
for i in range(len(A)):
for j in range(len(A[i])):
if A[i][j+2] != 1:
print A[i]
But when I run the function it finds one list but then prints that list over and over again before giving me an IndexError saying the list index is out of range. This seems to be a fairly easy problem but for some reason I'm not getting it. Any help would be really appreciated.
The problem is these two lines:
for j in range(len(A[i])):
if A[i][j+2] != 1:
What'll happen is that you'll eventually get to a point where j is the length of your list, minus 1. But then you're calling j+2 in the below code, and that's guaranteed to create a number longer than your list, giving you the IndexError. You can fix that with:
for j in range(2,len(A[i])):
if A[i][j] != 1:
As for the endless printing, you're nearly there, but you'll want to stop the loop if you find the non-1 element.
if A[i][j] != 1:
print A[i]
break
Alternately, the other answers will give you the same result more easily. But that's where your current errors are coming from.
for list in A:
if 1 not in list[3:]:
print list
even another solution:
lst = [
[1,2,3],
[1,1,1],
[3,4,5],
[3,5,6],
] # +++
def has1(subLst):
return subLst.count(1) == 0
print filter(has1, lst)
This avoids out of range issues.
def discover(A):
results = []
for lst in A:
for i in lst[3:]:
if i != 1:
results.append(lst)
break
return results
In addition to the other answers here, one could also make use of a generator. The yield statement will allow you to skirt establishing a default list to place your results into; you can just specify the condition you're looking for and yield the result.
>>> def discover(lists):
... for l in lists:
... if not [x for x in l[2:] if x != 1]:
... yield l
>>> stuff = [[2, 3, 4, 5, 1, 2], [2, 5, 1, 1, 1, 1, 1]]
>>> results = discover(stuff) #returns <generator object discover at 0x105e3eb90>
>>> results.next()
[2, 5, 1, 1, 1, 1, 1]
>>>
The magic line here being, if not [x for x in l[2:] if x !=1]. It builds a list from l[2:] and checks that any variable in there does not equal 1; if the list has no length, it means there are no non-1 entries in l[2:] and so it yields l.
A query to check if any element (after the second) != 1 would be:
any(x != 1 for x in mylist[3:])
so
def discover(A):
for mylist in A:
if any(x != 1 for x in mylist[3:]):
print mylist
I'm trying to create a function that returns all the circular numbers from a given number, and it's giving me an odd result. The function is:
def getcircs(mylist):
circs=[]
x=mylist
y=list(x)
dig=len(x)-1
j=0
circs.append(x)
while j < dig:
for i in range(0,dig):
r=i+1
g=x[r]
y[i]=g
y[dig]=x[0]
print y
circs.append(y)
x=list(y)
j+=1
print circs
return circs
And as you can see when you run it, the lists 'y' are returning what I'm looking for, but the list 'circs' doesn't seem to have the right 'y' value appending to it. I'm wondering if it's an issue with the way Python references lists, but I can't figure it out. Thanks.
This is because lists are by reference and you re-use y. When you append y to circs, circs gets another reference to y. When you later modify y, you will see the change in each spot in circs where y was appended. Try making a copy of y and working with that.
def getcircs(mylist):
circs=[]
x=mylist
y=list(x)
dig=len(x)-1
j=0
circs.append(x)
while j < dig:
temp = y[:]
for i in range(0,dig):
r=i+1
g=x[r]
temp[i]=g
temp[dig]=x[0]
print temp
circs.append(temp)
x=list(temp)
j+=1
print circs
return circs
The line temp = y[:] just creates temp as a full slice of y, which natively produces a copy.
In case you want to do it a simpler way (in my opinion anyway) you might benefit from using itertools.cycle here. This approach could be cleaned up too, but you get the idea:
import itertools
my_list = [1, 2, 3, 4]
cycler = itertools.cycle(my_list)
list_size = len(my_list)
for i in range(list_size):
print [cycler.next() for j in range(list_size)] # call next on the cycler generator
cycler.next() # skip the next number
OUTPUT
[1, 2, 3, 4]
[2, 3, 4, 1]
[3, 4, 1, 2]
[4, 1, 2, 3]
In fact, here is a one-liner for it:
print [[cycler.next() for j in range(list_size + 1)][:-1] for i in range(list_size)]
OUTOUT
[[1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]