0

I'm not to confident that I am asking this question correctly but this is what I'd like to do.

In django admin, I would like to write an action that sorts the list of my contestants randomly and doesn't allow two people with the same first name to be within 4 records of eachother. So basically, if you have John L. John C. Carey J, Tracy M. Mary T., the records would be listed like this:

John L.

Mary T.

Carey J.

Tracy T.

John C.

              OR

How can I write an action that would create random groups where two people with the same name wouldn't be within the same group like so:

John L. John C. Carey J, Tracy M. Mary T. =

Group 1

John L.

Mary T.

Carey J.

Tracy T.

Group 2

John C.

Forgive me if it isn't very clear, let me know and I'll try to specify further but any help would be appreciated

EDIT: 
Is this what you are referring to? I can't quite figure out how to compare the fields to see if they are the same

   Model:
class people(models.Model)
   fname = model.CharField()
   lname = model.CharField()
   group = model.IntegerField()


 View:
   N = 4
   Num = randint(0, N-1)
   for x in queryset:
       x.group = Num
       if group == group| fname == fname | lname == lname:
           x.group = (Num + 1) % N
user3806832
  • 663
  • 9
  • 22
  • I think I didnt understand properly, do you want a group by and after that use order? Can you explain how you would like to do it in SQL? – Lara Jul 28 '14 at 08:56

1 Answers1

0

Your first question cannot be solved always. Just think of all contestants have the same name, then you actually cannot find a solution to it.

For the second question, I can suggest an algorithm to do that, though. Since I do not see any restriction on the number of groups, I will suggest a method to create the least number of groups here.

EDIT: I assumed you don't want 2 people with same "First name" in a group.

The steps are

  1. Count the appearance of each name

    count = {}
    for x in queryset:
        if x.fname not in count:
             count[x.fname] = 0
        count[f.name] += 1
    
  2. Find the name with the most appearance

    N = 0
    for x in queryset:
        if count[x.fname] > N:
            N = count[x.fname]
    
  3. Create N groups, where N equals to the number of appearance of the name in step 2

  4. For each name, generate a random number X, where X < N.

    Try to put the name into group X. If group X has that name already, set X = (X + 1) % N and retry, repeat until success. You will always find a group to put the contestant.

    from random import randint
    groups = [[]] * N
    for item in queryset:
        X = randint(0, N-1)
        while item.fname in groups[X]:
            X = (X + 1) % N
        groups[X].append(item.fname)
        item.group = X
    

EDIT:

Added details in steps 1, 2, 4.

From the code segment in your edited, I think you do not actually need a definition of "group" in model, as seems you only need a group number for it.

  • is this what you had in mind? N = 4 Num = randint(0, N-1) for x in queryset: x.group = Num if group == group & fname == fname | lname ==lname: x.group = (Num + 1) % N I cant quite figure out how to compare the fields to see if they are the same – user3806832 Jul 29 '14 at 02:58
  • Since you didn't provide the actual model, I only gave a concept on how to do that. I didn't know how your data was stored so I had no way to tell how to compare the "name". It's much better now that you have your model provided. –  Jul 29 '14 at 03:33
  • I like where it seems to be going if only I can compare those fields to keep them from being in the same group twice. Any ideas? – user3806832 Jul 29 '14 at 03:39
  • Please specify how do you want to compare the name, by first name? full name? I guess your example is comparing first name, but the code is comparing full name, it's quite confusing. N is not hardcoded. You have to follow step 1 and step 2 to find out N. You can use a dict to do step 1 and step 2. I'll edit my answer to show this. –  Jul 29 '14 at 03:47
  • I would like to compare by full name. Yes I understand that N is not hard coded, it was just a quick way for me to test out the code because although I get what you're telling me to do I still have to work out how to do it (I'm still pretty new :]). Finally I just realize that I'd probably to to set a limit to the amount of people that can be in one group to make the groups as equal as I can (I expect if there arent enough people, the last group would have fewer people than the others) - AND Thank you so much, I at least have an idea of where to go where as before, I didnt. – user3806832 Jul 29 '14 at 04:04
  • You're welcome. It should not be difficult to use full name. Just a reminder, if you put a limit on the total number of people on each group, and you put people randomly into the groups, you can sometimes go into a dead end. –  Jul 29 '14 at 04:15
  • I'm still working with it, trying to solve a key error that I got but this definitely deserves best answer, I learned a lot. I'll look further into the limiter – user3806832 Jul 29 '14 at 04:27