В Django, как написать запрос, который выбирает все возможные комбинации из четырех целых чисел? - PullRequest
1 голос
/ 27 октября 2009

Я пишу игровой сайт, где розыгрыш представляет собой серию из четырех цифр. например, 1234

Я пытаюсь написать запрос в django, который выберет всех победителей на основе четырех введенных цифр. Победители - это любая комбинация одинаковых чисел или одинаковой комбинации, 1 2 3 4, 2 3 1 4, 4 1 3 2 все победители.

как наиболее эффективно написать этот запрос.

--------------------- Отредактируйте, извините за то, что не предоставили образцы моделей здесь ниже: -----------

class Draw(models.Model):
    digit1 = models.PositiveSmallIntegerField(null=True,blank=True)
    digit2 = models.PositiveSmallIntegerField(null=True,blank=True)
    digit3 = models.PositiveSmallIntegerField(null=True,blank=True)
    digit4 = models.PositiveSmallIntegerField(null=True,blank=True)
    draw_date = models.DateTimeField()
    closed = models.BooleanField()
    winner = models.BooleanField()

    def __unicode__(self):
        return "Draw For Week Ending %s" %(self.draw_date)

    def get_absolute_url(self):
        return "/draw/%s/" % (self.draw_date)

    def save(self, force_insert=False, force_update=False):
        if self.digit1 and self.digit2 and self.digit3 and self.digit4:
            #check if there are winners
            try:
                winners = Ticket.objects.filter(draw=self.id,digit1=self.digit1,digit2=self.digit2,digit3=self.digit3,digit4=self.digit4)
                self.winner = True
            except Ticket.DoesNotExist:
                self.winner = False                
            #close & save draw/winners
            self.closed = True
            # Add new Draw for following week.
            new_date = self.draw_date + datetime.timedelta(hours=168)
            new_draw= Draw(draw_date=new_date)
            new_draw.save()
        super(Draw, self).save(force_insert, force_update) # Call the "real" save() method.

class Serial(models.Model):
    serial = models.CharField(max_length=4)
    closed = models.BooleanField(unique=False)

    def __unicode__(self):
        return "%s" %(self.serial)

    def get_absolute_url(self):
        return "/draw/serial/%s/" % (self.serial)    

class Ticket(models.Model):
    draw = models.ForeignKey(Draw)
    digit1 = models.PositiveSmallIntegerField()
    digit2 = models.PositiveSmallIntegerField()
    digit3 = models.PositiveSmallIntegerField()
    digit4 = models.PositiveSmallIntegerField()
    date = models.DateField(auto_now_add=True,editable=False)
    active = models.BooleanField(default=True)
    serial_used = models.ForeignKey(Serial,related_name="ticket_serial_used")

    def __unicode__(self):
        return "#: %s - %s" %(self.id,self.draw)

    def get_absolute_url(self):
        return "/ticket/%s/" % (self.id)    

    def save(self, force_insert=False, force_update=False):
        if self.serial_used:
            serial = Serial.objects.get(pk=self.serial_used.id)
            serial.closed = True
            serial.save()
        super(Ticket, self).save(force_insert, force_update) # Call the "real" save() method.

Ответы [ 3 ]

5 голосов
/ 27 октября 2009

Я бы посоветовал изменить код, чтобы сохранить цифры, чтобы они сохранялись в отсортированном порядке. Например. если пользователь вводит «5262», он должен сохранить это как «2256». Затем, когда вы выбираете выигрышный набор цифр, вы можете отсортировать их и отфильтровать по простому равенству. Это будет работать намного лучше, чем пытаться проверить все возможные комбинации.

Если вам нужен несортированный выбор для других целей, добавьте в модель новое поле sortedDigits или что-то еще, чтобы вы могли сравнить его с

0 голосов
/ 27 октября 2009

Важен ли порядок чисел?

Если нет, вы можете отсортировать цифры для билетов и розыгрышей в порядке возрастания, а затем использовать свой код

winners = Ticket.objects.filter(draw=self.id,digit1=self.digit1,digit2=self.digit2,digit3=self.digit3,digit4=self.digit4)

Кроме того, Ваша попытка ... кроме блока не поймает ситуацию, когда нет победителей. Исключение DoesNotExist выдается методом get ( см. Документы ).

Если выигрышного билета нет, метод filter вернет пустой набор запросов, но не вызовет ошибку. Затем вы можете проверить, есть ли победители, используя оператор if.

if winners
    # there are winners
    self.winner = True
else:
    # there are not winners
    self.winner = False
0 голосов
/ 27 октября 2009

Код:

from itertools import permutations
winning_numbers = "1234"
winning_combinations = map(lambda v: "".join(v), list(permutations(winning_numbers, 4)))

winners = GamesPlayed.objects.filter(numbers__in=winning_combinations)

Предполагается, что GamesPlayed является модельным объектом для всех сыгранных игр с номерами текстового поля, содержащими четыре выбранных числа в формате NNNN.

Если вы на Python 2.5 itertools не имеет permutations. В документах есть реализация, которую вы можете использовать: http://docs.python.org/library/itertools.html#itertools.permutations

...