Home > other >  python infinite loop and numpy delete do not work properly
python infinite loop and numpy delete do not work properly

Time:11-05

I wrote a function and it does not end. Logically len(array) should be decreasing but it stuck in 227. I think numpy delete does not work properly or I made mistake somewhere??

def segmenting (file, threshold):
    segments = []
    check = True
    count = 0
    while check == True:
        if len(file) <= 2:
            check = False
        sequence = []
        ids = []
        for i in range(1, len(file)):
            vector = [file[i,1] - file[0,1] , file[i,2]- file[0,2] ]
            magnitude = math.sqrt(vector[0]**2   vector[1]**2)
            print(i)
            if magnitude <= threshold:
                sequence.append(file[i])
                ids.append(i)
            if i == len(file) and len(sequence) == 0:
                file = np.delete(file, 0 , axis = 0)
                break
        
        if len(ids) >0 and len(sequence)>0 :
            segments.append(sequence)
            file = np.delete(file, ids , axis = 0)
        print('sequence after :',sequence)        
        sequence = []
        ids = []
        print(len(file))

    return segments

CodePudding user response:

It's likely due to the fact you are removing element from file array within a for loop, and also trying to iterate over for loop using file array. Try iterate over a clean version of file array(no modification on it), and do the deletion on a copy of file array

For example, one possible solution is to fix this line

for i in range(1, len(file)):

Fix like below

N=len(file)
for i in range(1, N):

Also you could remove flag variable 'check' and replace with break statement

CodePudding user response:

The following (simplified) logic will never be executed

for i in range(1, len(file)):
   if i == len(file):
       file = np.delete(file, 0)

Without having a way to remove the first line of the file, you have no way to exhaust your array. This check is superfluous anyway since after each iteration you won't need the first line anymore.

As a first fix you can put the check outside the loop and only check whether you've found any matches

for i in range(1, len(file)):
    ...
if len(sequence) == 0:
    file = np.delete(file, 0)

But that way you would have one iteration where you find (and remove) matches and then one more with no more matches where you then remove it. Therefore, as said above, you should always remove the first line after each iteration.

With more simplifications, your code can be reduced down to:

def segmenting(file, threshold):
    segments = []
    while len(file) > 2:
        idx = np.sqrt(np.sum((file[1:,1:3] - file[0,1:3])**2, axis=1)) <= threshold
        file = file[1:]
        segments.append(list(file[idx]))
        file = file[np.logical_not(idx)]
    return segments
  • Related