Nested loop through list avoiding same element - python

I can't explain the concept well at all, but I am trying to loop through a list using a nested loop, and I can't figure out how to avoid them using the same element.
list = [1, 2, 2, 4]
for i in list:
for j in list:
print(i, j) # But only if they are not the same element
So the output should be:
1 2
1 2
1 4
2 1
2 2
2 4
2 1
2 2
2 4
4 1
4 2
4 2
Edit as the solutions don't work in all scenarios:
The if i != j solution only works if all elements in the list are different, I clearly chose a poor example, but I meant same element rather than the same number; I have changed the example

You can compare the indices of the two iterations instead:
lst = [1, 2, 2, 4]
for i, a in enumerate(lst):
for j, b in enumerate(lst):
if i != j:
print(a, b)
You can also consider using itertools.permutations for your purpose:
lst = [1, 2, 2, 4]
from itertools import permutations
for i, j in permutations(lst, 2):
print(i, j)
Both would output:
1 2
1 2
1 4
2 1
2 2
2 4
2 1
2 2
2 4
4 1
4 2
4 2

Simply:
if i != j:
print(i, j)

Related

How to derive the following pattern with Python

How can I make the following pattern with Python, I thought about everything, but I didn't get anywhere
Problem solved, thanks to all contributors
Why negativity?
Well, if stackoverflow is not for asking questions, then what is it for???
The displayed numbers are always the maximum of the row number and column number they appear at.
So, to print that pattern, you could do something line this:
def solve(n):
for row in range(1, n + 1):
for col in range(1, n + 1):
print(max(row, col), end=" ")
print("\n")
solve(5)
As you posted an image, it is not clear whether there should be empty lines between the lines with numbers, and whether at the end it is fine to have trailing newline characters or not.
Also check whether there are requirements as to how the pattern should look when the size of the matrix is more than 9.
But it should not be hard to adapt the code accordingly.
Here's another approach:
numbers = [1, 2, 3, 4, 5]
for i in range(len(numbers)):
for j in range(i):
numbers[j] += 1
print(*numbers)
Output:
1 2 3 4 5
2 2 3 4 5
3 3 3 4 5
4 4 4 4 5
5 5 5 5 5
import numpy as np #Just to format as matrix when printing
a=[[max(r,c) for r in range(1,6)] for c in range(1,6)]
print(np.array(a))
>>> [[1 2 3 4 5]
>>> [2 2 3 4 5]
>>> [3 3 3 4 5]
>>> [4 4 4 4 5]
>>> [5 5 5 5 5]]

What will be the best approach for a digit like pattern in python?

i was trying a pattern in Python
if n == 6
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
after trying to think a lot
i did it like this --->
n = 6
for i in range(1,n):
x = 1
countj = 0
for j in range(i,n):
countj +=1
print(j,end=" ")
if j == n-1 and countj < n-1 :
while countj < n-1:
print(x , end =" ")
countj +=1
x +=1
print()
but i don't think it is the best approach, I was trying to search some better approach , but not able to get the proper one, So that I came here,, is there any possible better approach for the problem?
I would do like this, using a rotating deque instance:
>>> from collections import deque
>>> n = 6
>>> d = deque(range(1, n))
>>> for _ in range(1, n):
... print(*d)
... d.rotate(-1)
...
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
There is a similar/shorter code possible just using range slicing, but maybe it's a bit harder to understand how it works:
>>> ns = range(1, 6)
>>> for i in ns:
... print(*ns[i-1:], *ns[:i-1])
...
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
You could also create a mathematical function of the coordinates, which might look something like this:
>>> for row in range(5):
... for col in range(5):
... print((row + col) % 5 + 1, end=" ")
... print()
...
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
A too-clever way using list comprehension:
>>> r = range(5)
>>> [[1 + r[i - j - 1] for i in r] for j in reversed(r)]
[[1, 2, 3, 4, 5],
[2, 3, 4, 5, 1],
[3, 4, 5, 1, 2],
[4, 5, 1, 2, 3],
[5, 1, 2, 3, 4]]
more-itertools has this function:
>>> from more_itertools import circular_shifts
>>> circular_shifts(range(1, 6))
[(1, 2, 3, 4, 5),
(2, 3, 4, 5, 1),
(3, 4, 5, 1, 2),
(4, 5, 1, 2, 3),
(5, 1, 2, 3, 4)]
You can use itertools.cycle to make the sequence generated from range repeat itself, and then use itertools.islice to slice the sequence according to the iteration count:
from itertools import cycle, islice
n = 6
for i in range(n - 1):
print(*islice(cycle(range(1, n)), i, i + n - 1))
This outputs:
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
Your 'pattern' is actually known as a Hankel matrix, commonly used in linear algebra.
So there's a scipy function for creating them.
from scipy.linalg import hankel
hankel([1, 2, 3, 4, 5], [5, 1, 2, 3, 4])
or
from scipy.linalg import hankel
import numpy as np
def my_hankel(n):
x = np.arange(1, n)
return hankel(x, np.roll(x, 1))
print(my_hankel(6))
Output:
[[1 2 3 4 5]
[2 3 4 5 1]
[3 4 5 1 2]
[4 5 1 2 3]
[5 1 2 3 4]]
Seeing lots of answers involving Python libraries. If you want a simple way to do it, here it is.
n = 5
arr = [[1 + (start + i) % n for i in range(n)] for start in range(n)]
arr_str = "\n".join(" ".join(str(cell) for cell in row) for row in arr)
print(arr_str)

How to save and work with previous iteration in loop?

You could somehow hold it in a loop after the first iteration and store it in a variable and then continue on. So that in one variable there is a standard loop and in the other a previous loop?
example:
import numpy as np
for j in np.arange(0,5):
print(j)
0
1
2
3
4
5
6
i need example
0
1 0
2 1
3 2
4 3
5 4
6 5
just save the variable you want to print next, and print it before change it with the next one
num = 0
for j in np.arange(0,5):
print(num)
num = j
import numpy as np
for j in np.arange(0,7):
if j == 0:
print(j)
continue
print(j, j-1)
Use zip and itertools.tee:
itr1, itr2 = tee(np.arange(0, 5))
i, j = next(itr1), None
print(i, j)
for i, j in zip(itr1, itr2):
print(i, j)
outputs
0 None
1 0
2 1
3 2
4 3
The question is poorly worded, but here's a good basic iteration. It keeps track of the current variable, as well as saving it.
In [161]: alist = [1,3,6,9,12]
...: blist = []
...: latest = None
...: for item in alist:
...: blist.append(item)
...: print(latest, blist[-1])
...: latest = item
...: print(blist)
None 1
1 3
3 6
6 9
9 12
[1, 3, 6, 9, 12]
In the iteration, the current value is item, the previous is latest. blist[-1] is the last added item.

How do you use the range function to count from 0 to 8 by increments of 1 for each iteration in a for loop

I have a triple for loop that creates a 1 row and 2 column collection of numbers starting at 0 0 and going up to 2 2. The third for loop counts from 0 to 8. The code looks as follows:
for N in range(0,3):
for K in range(0,3):
print(N,K)
for P in range(0,9):
print(P)
If you run this code you get the obvious output:
0 0
0
1
2
3
4
5
6
7
8
0 1
0
1
2
3
4
5
6
7
8
0 2
0
1
2
3
4
5
6
7
8
...
And so on. I want instead of the output of 0 to 8 after the N K printout, instead something that looks like:
0 0
0
0 1
1
0 2
2
1 0
3
1 1
4
1 2
5
2 0
6
2 1
7
2 2
8
My first guess was an if statement that said:
if P == Q:
break
where Q was several sets of sums and even the N,K array. However, I couldn't figure out the best way to get my
wanted output. I do think an if statement is the best way to achieve my wanted result, but I'm not quite sure of how to approach it. P is necessary for the rest of my code as it will be used in some subplots.
As this is just an increment by one at each print, you can just do compute the index with N * 3 + K
for N in range(0, 3):
for K in range(0, 3):
print(N, K)
print(N * 3 + K)
CODE DEMO
You can use zip to traverse two iterables in parallel. In this case, one of the iterables is the result of a nested list. That can be handled by using itertools.product, as follows:
import itertools
for (N, K), P in zip(itertools.product(range(3), range(3)), range(9)):
print(N, K)
print(P)

For loop iteration with range restarting at index 1

I'm trying to iterate through a loop with a step of 2 indexes at the time and once it reaches the end to restart the same but from index 1 this time rather than zero.
I have already read different articles on stack like this with a while loop workaround. However, I'm looking for an option which will simply use the element in my for loop with range and without using itertool or other libraries or a nested loop:
Here is my code:
j = [0,0,1,1,2,2,3,3,9,11]
count = 0
for i in range(len(j)):
if i >= len(j)/2:
print(j[len(j)-i])
count += 1
else:
count +=1
print(j[i*2],i)
Here is the output:
0 0
1 1
2 2
3 3
9 4
2
2
1
1
0
The loop does not start back from where is supposed to.
Here is the desired output:
0 0
1 1
2 2
3 3
9 4
0 5
1 6
2 7
3 8
11 9
How can I fix it?
You can do that by combining two range() calls like:
Code:
j = [0, 0, 1, 1, 2, 2, 3, 3, 9, 11]
for i in (j[k] for k in
(list(range(0, len(j), 2)) + list(range(1, len(j), 2)))):
print(i)
and using an itertools solution:
import itertools as it
for i in it.chain.from_iterable((it.islice(j, 0, len(j), 2),
it.islice(j, 1, len(j), 2))):
print(i)
Results:
0
1
2
3
9
0
1
2
3
11
Another itertools solution:
import itertools as it
lst = [0, 0, 1, 1, 2, 2, 3, 3, 9, 11]
a, b = it.tee(lst)
next(b)
for i, x in enumerate(it.islice(it.chain(a, b), None, None, 2)):
print(x, i)
Output
0 0
1 1
2 2
3 3
9 4
0 5
1 6
2 7
3 8
11 9

Categories