简体   繁体   中英

Can anyone help me through what I think might be an infinite loop?

What I am trying to do with the code below is a sort of group check. I have assigned people to groups using group numbers so:

fname lname  group
mark  anthony 2
macy  grey    3      etc..

I want to prevent any two people with the same first and last names from being in the same group. So I wrote an action to try to do this but I think I may have found myself in an infinite loop, either way its not working.

def groupcheck(modeladmin, request, queryset):

    groups=[]
    N = 7       # number of groups
    for X in queryset:
        item = "".join([X.fname, X.lname, str(X.group)])     #the information I am trying to check 

        if item in groups:     # check if it is the array above (groups)
           while item in groups: 
             G = X.group
             Y = int(G) + int(1)    #change the group number
             if Y > N:      # This is my attempt to not allow the group number to be more than the number of groups i allowed (N)
                Y = 0
             removeditemnumber = ''.join([i for i in item if not i.isdigit()]) # I am removing the group number 
             item = removeditemnumber + str(Y)       # now I am trying to replace it
           groups.append(item)     #once the loop is done i want the edited version to be added to the array
           X.group = Y
           X.save()        # I want the new group number to be saved to the databse
        else:
           groups.append(item)

I tried to add comments to help guide through the code in case I did it wrong, if it's distracting let me know and i will remove them, please help if you can

I would suggest refactoring this entirely and taking a different approach. You're essentially mapping group numbers to to groups of people, so this sounds like the perfect place to use a dictionary instead. Try this:

import pprint

name_list = [
        "mark   anthony 2",
        "macy   grey    3",
        "bob    jones   4",  
        "macy   grey    6",  
        "mike   johnson 5",
        "macy   grey    6",
        "mark   anthony 2"]

pprint.pprint(name_list)

N = 7

# create a dictionary where the keys are gorup numbers
groups = {n:[] for n in xrange(N)}

# this lambda function will increment the input up to N
# then wrap around to zero
increment = lambda x: x+1 if x+1 < N else 0

for name in name_list:
    fname, lname, group_num = name.split()

    group_num = int(group_num)
    old_group = group_num

    # increment the group number while the name is in
    # the current group
    while (fname, lname) in groups[group_num]:
        group_num = increment(group_num)
        if group_num == old_group:
            # if we've checked all the groups and there's
            # no space for this name, raise exception
            raise NoMoreSpaceError

    # we found a spot! add the current name to the current
    # group number
    groups[group_num].append((fname, lname))

pprint.pprint(groups)

Output:

['mark anthony 2',
'macy grey 3',
'bob jones 4',
'macy grey 6',
'mike johnson 5',
'macy grey 6',
'mark anthony 2']

{0: [('macy', 'grey')],
1: [],
2: [('mark', 'anthony')],
3: [('macy', 'grey'), ('mark', 'anthony')],
4: [('bob', 'jones')],
5: [('mike', 'johnson')],
6: [('macy', 'grey')]}

Notice that in the input, there were two instances of "mark anthony" assigned to group 2, so one got bumped to group 3. Two instances of of "macy grey" stayed where they are (groups 3 and 6) because they are in different groups, but the second one that was assigned to group six got bumped around to group 0. Now you end up with an organized dictionary, and I think this code is much easier to follow and maintain. For now, I've raised an exception if there are too many occurances of a specific name, but you'll have to decide how you want to handle that.

I removed all the extra stuff from your code. Havent checked it. There should only be minor errors.

  groups = []
  N = 7

  for X in queryset:
    item = "".join([X.fname, X.lname, str(X.group)])     
    nCount = 0
    while item in groups:
      X.group = (X.group + 1)%N 
      item = "".join([X.fname, X.lname, str(X.group)])  

      # This part only checks for a very stringent condition. Mostly 
      # unnecessary for real names. Only the couple of lines above
      # are meaningful as far as the code is concerned. 
      nCount += 1
      if nCount > N: 
        print X.fname, X.lname, 'exists in all', N, 'groups ...'
        sys.exit(1)

    groups.append(item)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM