Nested loop over the elements of the same array - python-3.x

I have a numpy array:
a = np.array([0, 1, 2, 3, 4, 5])
I would like to iterate over each element and compute a statistic using all the elements except the one at the current index. Statistic would require looping over each element.
stats = np.array([])
for ind1,x in enumerate(a):
s = 0
for ind2,y in enumerate(a):
if ind2 != ind1:
s = s + compute_stat(y)
stats[ind1] = s
It looks like I might mask the current index, however, I would then need to reset the mask within each loop.
a = np.array([0, 1, 2, 3, 4, 5])
a = np.ma.array(a)
for ind1,x in enumerate(a):
a[ind1] = np.ma.masked
What is the best way to use a nested loop in this case to iterate a computation over (n-1) elements of the same array?
Thank you

Related

If there is a duplicate in a list, how do I delete ALL occurrences of item? [duplicate]

I have a list like this:-
[1,2,3,4,3,5,3,6,7,8]
I want to remove the repeating element (here:- 3) completely from the list like this:-
[1,2,4,5,6,7,8]
How do I implement this in python such that not only the first occurrence of duplicate element is removed but all the duplicating values are removed
You can use Counter from collections to count the number of occurrences and select those elements which appear exactly once using a list comprehension:
from collections import Counter
a = [1,2,3,4,3,5,3,6,7,8]
[k for k, v in Counter(a).items() if v == 1]
(Counter basically returns a dictionary where elements are stored as keys and their counts are stored as values.)
This code should work
#Finding duplicate
def dup(x):
s = len(x)
duplicate = []
for i in range(s):
k = i + 1
for j in range(k, s):
if x[i] == x[j] and x[i] not in duplicate:
duplicate.append(x[i])
return duplicate
#begining
list1 = [1, 2, 3, 4, 3, 5, 3, 6, 7, 8]
#Finding duplicate
dup_list = (dup(list1))
#removing duplicates from the list
final_list = list(set(list1) - set(dup_list))
print(final_list)
A good and efficient way will be to use pandas
import pandas as pd
sample_list = [1,2,3,4,3,5,3,6,7,8]
unique_list = list(pd.Series(sample_list).drop_duplicates())
>> unique_list
>> [1, 2, 3, 4, 5, 6, 7, 8]
Use a set. To get rid of all repeating values use this:
a = [1,2,3,4,3,5,3,6,7,8]
print(a)
a = list(set(a))
print(a)
That will output
[1,2,3,4,3,5,3,6,7,8]
[1,2,4,5,6,7,8]

Reverse operation of torch.unique

In pytorch , unique (with return_count is True) operation do like this
[1,1,2,2,3,3] => ([1,2,3],[2,2,2])
Are there any reverse operations of torch.unique() ?
i.e Given a unique list and its count , return the original list like
([1,2,3],[2,2,2]) = > [1,1,2,2,3,3]
If you include the return inverse parameter it will return the indices for where elements in the original input ended up in the returned unique list. Then you can use take to create a new tensor.
test_tensor = torch.tensor([1,1,2,2,3,3])
items, inverse, counts = test_tensor.unique(return_counts=True, return_inverse=True)
new_tensor = torch.take(items, inverse)
assert new_tensor.eq(test_tensor).all() # true
EDIT:
If you only have a list and the counts this code should give you what you want using repeat. Not sure if a pure pytorch function exists.
test_tensor = torch.tensor([1,1,2,2,3,3])
items, counts = test_tensor.unique(return_counts=True)
new_tensor = torch.tensor([], dtype=torch.int64)
for item, count in zip(items, counts):
new_tensor = torch.cat((new_tensor, item.repeat(count)))
assert new_tensor.eq(test_tensor).all() # true
You probably want torch.repeat_interleave(). You can use it like this:
>>> x = torch.tensor([1, 1, 2, 3, 3, 3])
>>> v, c = torch.unique(x, return_counts=True)
>>> v, c
(tensor([1, 2, 3]), tensor([2, 1, 3]))
>>> torch.repeat_interleave(v, c)
tensor([1, 1, 2, 3, 3, 3])

the terminal doesn't display when i compile the code

I want to create a program, such that it returns the index of the element, if each element in list 1 matches the corresponding element in list 2
for example: [5, 1, -10, 3, 3], [5, 10, -10, 3, 5].
Here 5 in list 1 matches the first element 5 in list 2 hence it returns index 0. similarly -10 matches with -10. hence gives index 2.
required output
[0,2,3]
MY CODE:
def same_values(lst1,lst2):
n = 1
lst_of_index = []
while(n <= len(lst1)):
for i in lst1:
value_1 = i
for j in lst2:
value_2 = j
if (value_1 == value_2):
indexed_value = lst1.index(i)
lst_of_index.append(indexed_value)
n += 1
return lst_of_index
print(same_values([5, 1, -10, 3, 3], [5, 10, -10, 3, 5]))
when i run the code, it doesn't display anything. Is something wrong with my code?
Combining the answers from #user12137152 and #diego-mourino with a list comprehension, you get a relatively simple one liner:
def same_values(lst1,lst2):
return [idx for idx, val in enumerate(zip(lst1, lst2)) if val[0] == val[1]]
Use a for loop and zip to iterate over both the lists at the same time. The benefit of the following program is that it doesn't crashes even if the lists are of different sizes.
def same_values(lst1, lst2):
lst_of_index = []
n = 0
for i, j in zip(lst1, lst2):
if i == j:
lst_of_index.append(n)
n += 1
return lst_of_index
print(same_values([5, 1, -10, 3, 3], [5, 10, -10, 3, 5]))
The function you implementate has a major bug. The function doesn´t return anything because you are generating an infinite loop. That`s because you first iterate over all the values of the lists and, after that, you compare value_1 and value_2. In this example, the value_1 and value_2 will be 3 and 5 respectively (because you are comparing the last value of the lists because the if statement is after the two iterators over the lists at the same indentation level). And because of that, the while loop gets stuck.
I propose to you an alternative implementation, using enumerate() instead of a the while. When you use enumerate over a list, this iterator give you 2 elements: the position of a given element of the list (i) and the element of the list (in this case, value_1). This implementation is shown below:
def same_values(lst1,lst2):
lst_of_index = []
for i, value_1 in enumerate(lst1):
value_2 = lst2[i]
if (value_1 == value_2):
lst_of_index.append(i)
return lst_of_index

Selection sort using python3

def selection_sort(li):
new_list = []
a = li[0]
for x in range(1, len(li)):
if li[x] < a:
a = li[x]
new_list = a
print(new_list)
b = [1, 2, 5, 3, 7, 4]
selection_sort(b)
Why does the above code returns empty list.
Thank you
Learn what is selection sort using visualization. Do follow the steps how to use selection sort
def selection_sort(li):
for i in range(len(li)):
min_idx = i
for j in range(i+1, len(li)):
if li[min_idx] > li[j]:
min_idx = j
li[i], li[min_idx] = li[min_idx], li[i]
print(li)
b = [1, 2, 5, 3, 7, 4]
selection_sort(b)
Now, from your code perspective, your selection sort algorithm isn't correct. Furthermore, you don't need to initialize another list to store sort element rather your function parameter list is kind enough to store the sort element.

For Loop only printing of 1? Python

I was trying to print a list in backwards order using a for loop, however my code only prints of a 1, any ideas why?
sorted_list = ["jack",4,3,1,"jill",4,1,0,"bob",0,0,10,"tim",5,3,1,"sod",3,1,0]
des_list = []
for i in range(len(sorted_list)-2,-3,-1):
des_list.append(sorted_list[i-2])
des_list.append(sorted_list[i - 1])
des_list.append(sorted_list[i])
des_list.append(sorted_list[i+1])
print(des_list)
It would probably be easier to store the chunks of data into objects. That way, you can just call reversed() on the list of objects and handle the data that way.
If you want to keep the list in the format you have, you can loop through the list in "chunks", like this: for i in range(0, len(sorted_list), 4):.
So, for every 4 elements in the list, grab the chunk of of data using list slicing notation: sorted_list[i:i+4] and insert it to the front of the destination list.
Putting that together, you get this code:
sorted_list = ["jack",4,3,1,"jill",4,1,0,"bob",0,0,10,"tim",5,3,1,"sod",3,1,0]
des_list = []
for i in range(0, len(sorted_list), 4):
des_list.insert(0, sorted_list[i:i+4])
print(des_list)
That will output this: [['sod', 3, 1, 0], ['tim', 5, 3, 1], ['bob', 0, 0, 10], ['jill', 4, 1, 0], ['jack', 4, 3, 1]].
Keep in mind that that code will give you a list of lists, because sorted_list[i:i+4] returns a list, which is why it might be easier to use objects instead.
If you don't want to have a list of lists, you can reverse the sliced list, loop through each element in the reversed sliced list, and insert it one at a time to the destination list.
Doing that, you get this code:
sorted_list = ["jack",4,3,1,"jill",4,1,0,"bob",0,0,10,"tim",5,3,1,"sod",3,1,0]
des_list = []
for i in range(0, len(sorted_list), 4):
for j in reversed(sorted_list[i:i+4]):
des_list.insert(0, j)
print(des_list)
Which outputs this: ['sod', 3, 1, 0, 'tim', 5, 3, 1, 'bob', 0, 0, 10, 'jill', 4, 1, 0, 'jack', 4, 3, 1]

Resources