• Не создается срез в python. Ошибка TypeError?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Давайте я помогу перевести этот текст для вас:
    TypeError: slice indices must be integers or None or have an __index__ method

    - Ошибка Типов: индексы среза должны быть целочисленными значениями или None или должны поддерживать метод __index__.
    Теперь посмотрите внимательно на строку, где произошла ошибка:
    full_downtime = string[downtime_border1:downtime_border2]

    Где же у вас тут индексы среза?
    -- Вот они: downtime_border1 и downtime_border2
    Давайте посмотрим какие значения у вас могут принимать эти переменные:
    downtime_border1 = ''
    downtime_border2 = ''

    Неожиданно!
    Что это а тип? Это целые числа? - нет
    Это None? - Нет!
    У них есть метод __index__?
    А что, черт возьми, вы хотели этим сказать в своей программе?
    На лицо не понимание кода. Вам слеует немного поучить основы питона.
    Ответ написан
    5 комментариев
  • Почему PyCharm подсвечивает жёлтым то, что работает?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Это специфика библиотеки, она представляет собой обёртку вокруг бинарной библиотеки и вот так вот в ней описаны интерфейсы нестандартно, что пичарм не видит сигнатур методов.
    Вы бы спросили на пикабу, там, точно знаю, сидит кто-то из джетбрейнс и довольно шустро отвечает. Наверняка там есть какая-то волшебная настройка для таких случаев.
    Но в целом подсвечивает и подсвечивает. И хрен бы с ним. Главное, чтобы юнит-тесты отрабатывали и интеграционные.
    Ответ написан
    Комментировать
  • Необходимо решить задачу для курса и понять в чем ошибка моего кода и мышления?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Александр Нестеров привёл решение на псевдокоде, но вопрос под тегом Питон... Дело в том, что питон не поощряет изменение входных строк в решениях такого рода.
    Поэтому приведу своё решение перфекциониста=) Если кто укажет как его улучшить, буду рад=)
    Возможно новичку применённые там трюки будут сложны в понимании или даже местами вредны, но точно познавательны.

    import unittest
    import typing
    
    _VARIANTS = []  # Сюда попадут все решения, которые нужно тестировать
    # А это декоратор, которым нужно пометить все претенденты на решение
    solution = lambda f: _VARIANTS.append(f) or f
    
    EXAMPLES = [
        ('', ''),
        ('a', 'a1'),
        ('abc', 'a1b1c1'),
        ('aaaabbca', 'a4b2c1a1'),
    ]
    
    
    @solution
    def encode(inp: str) -> str:
        """Самое простое решение
        Минусы: громоздко и многословно 
        (зато прозрачно и понятно, без магии и выкрутасов)
        """
        if not inp:
            return ''
        count = 1
        current = inp[0]
        res = []
        for c in inp[1:]:
            if c == current:
                count += 1
            else:
                res.append(f'{current}{count}')
                count = 1
                current = c
        
        res.append(f'{current}{count}')
        return ''.join(res)       
    
    
    def encode_stream(inp: typing.TextIO) -> typing.Iterator:
        """Потоковое решение. 
        С помощью него можно без затрат памяти кодировать файлы любого размера
        Минусы: нет, если вам нужно закодировать гигабайты. 
        Ну или готов поспорить на эту тему, если вы не согласны.=)
        """
        current = inp.read(1)
        count = len(current)
        while current:
            c = inp.read(1)
            if c == current:
                count += 1
            else:
                yield f'{current}{count}'
                current = c
                count = len(current)
    
    
    @solution
    def encode_string_by_stream(inp: str) -> str:
        """Обёртка для использования потокового кодирования из строки"""
        import io
        return ''.join(encode_stream(io.StringIO(inp)))
    
    
    @solution
    def encode_elegant(s: str) -> str:
        """Довольно элегантное решение на словаре от @seven5674.
        К сожалению в оригинальном варианте неверное, но я 
        исправил и отрефакторил.
        Минусы: запутанное и непрозрчное, зато короткое"""
        d = {}
        g = 1
        for c in s:
            g = d.get((c, g), 0) and g or g + 1
            d[c, g] = d.get((c, g), 0) + 1
    
        return ''.join([f'{k[0]}{v}' for k, v in d.items()])
    
    
    @solution
    def encode_by_regexp(s: str) -> str:
        """Решение на регекспах от @seven5674, 
        я лишь чуть отформатировал и отрефакторил.
        Минусы: регексп поведёт себя довольно непредсказуемо на больших данных,
        к тому же регекспы читать умеют не все. 
        Но автор умеет в регекспы лучше, чем в питон, видимо с js пришел.
        """
        import re
        return ''.join(
            f'{w}{len(l)}' 
            for l, w in 
            re.findall(r"((\w)+?(?!\2))", s)
        )
        
    
    #############################################################################
    ## Дальше идёт инфраструктура для тестирования решений
        
    class Test(unittest.TestCase):
        """Автоматический тест решений.
        Претенденты на решение должны быть помечены декоратором @solution
        Примеры берутся из списка EXAMPLES.
        """
    
        def closure(func, arg, res):
            """Временная функция, которая делает тест.
            Она формирует каждый раз новую функуию-замыкание, которая будет тестировать
            оережной кейс.
            """
            def test(self):
                f"""Тест функции {func.__name__}({arg!r})"""
                self.assertEqual(func(arg), res, msg=f'Func {func.__name__}({arg!r})')
            return test
        
        # Перебираем все варианты реализаций:
        for f in _VARIANTS:
            # Перебираем все предлженные эталонные римеры:
            for case_num, case in enumerate(EXAMPLES):
                # Создаём новую функуию теста и добавляем ее в класс теста как метод.
                locals()[f'test_{f.__name__}__{case_num}'] = closure(f, *case)
    
        # Удаляем из контекста класса лишние переменные
        del(closure, f, case_num, case)
    
    
    if __name__ == '__main__':
        unittest.main(verbosity=3)


    UPD: Обновил код, включив туда решения seven5674 и valerr007
    Кстати, решение valerr007 проваливает тест с "a" на входе. Возвращает пустую строку. Ну и много претензий к коду.
    Ответ написан
  • Как вступать в чаты telegram по всем видам ссылок?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Бот сам не может вступать в чаты, его должны добавлять люди.
    Иначе телеграмм бы давно утонул в спаме
    Ответ написан
  • Почему при вводе input() выдается ошибка?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Потому, что вместо числа вводишь пустую строку.
    Вот же написано, что неправильный литерал для десятичного числа. И даже указано какой именно литерал - пустая строка.
    А откуда она там? Видимо от того, что винда подаёт в буффер сдва символа /r/n в качестве абзаца.
    Оба они отсекают ввод через input, между ним ипустота. Так что до ввода 1 дело не доходит.
    Ответ написан
  • Как роботам видеть друг друга?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Можно. Фактически это триангуляция.
    Имеет смысл не просто светить маячками, а излучать модулированный сигнал, тогда его легче отличать от фоновой засветки. Вместо второго вращающегося датчика можно использовать зеркало. Тогда при быстром вращении вы будете видеть каждый маячок дважды: в своем зеркале и напрямую. По углам, на которых зарегистрированы пики можноопределить расстояние и направление до маячка.
    На вращающемся датчике вам нужен энкодер, который будет определять текущий угол попорота датчика.
    Это всё будет работать на плоскости. Если нужно в 3д, то проще поставить камеру и вычислять расстояние динамически, перемещая камеру.
    Ответ написан
    3 комментария
  • Попадает время в промежуток между двумя time или нет?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Да как-как? как обычно
    localtime >= open_time and localtime < close_time
    UPD:
    Не сразу понял в чем проблема.
    Речь, похоже, о заведениях типа ночных клубов, которые работают, скажем, с 22:00 до 05:00 и нужно понять попадает ли какое-то время в этот интервал, если два времени оказались по разную сторону от полуночи.
    Тут спасёт сложное условие:
    SELECT *
    FROM shop
    WHERE
    (open_time <= close_time) AND (localtime BETWEEN open_time AND close_time) OR
    (open_time > close_time) AND NOT (localtime BETWEEN close_time AND open_time)

    Это замечательно работает, если ваши магазины работают каждый день по одному графику, а если нет, то нужно строить расписание на неделю. Это доволно быстро работает, если хранить расписание в отдельной таблице в виде нтервалов работы в секундах от начала недели и ссылку (многие к одному) на учреждение.

    UPD2: Перенесу, пожалуй, сюда и пример с недельным расписанием из своего комментария.

    Интереснее когда график работы магазина разный в выходные и будни, причем, скажем, на выходных магазин открыт в полночь.
    Ну, к примеру, пн-пт - 10:00-23:00 а сб-вс - 10:00-01:00.
    Тут вообще интересно. Фактически магазин не работает в суботу с полуночи до часу ночи, но работает в понедельник с полуночи до часу ночи.
    В таких случаях расписание лучше задавать набором интервалов в часах, минутах или, обычно, в секундах от полуночи понедельника.
    В часах проще показывать на примере.
    0-1, 10-23 - понедельник
    34-47 - вторник
    и т.д.
    По-хорошему должен быть специальный бинарный тип данных, способный хранить такие интервалы эффективно и индексировать их.
    Очевидно. что для выше изложенного графика таких интервалов надо около 7+2 - по одному основному на каждый день, час после полуночи понедельника, и час после полуночи воскресенья.
    Итого 9 интервалов на магазин, если без перерывов. С обеденными перерывами будет 16 интервалов на магазин. В любом случае не критично. Просто нужно задавать реальное расписание магазина в формализованной форме (какой-то формулой) прямо в записи об этом магазине, а в таблицу с интервалами просто кэшировать развернутое расписание при апдейте формулы.
    У нас точно также интервалами с кэшированием в отдельной таблице было устроено расписание ВУЗа и всё работало мгновенно.
    Ответ написан
  • Какой алгоритм использовать для подбора ингредиентов по составу?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Выглядит как NP-полная задача, чем-то напоминающая задачу укладки многомерного рюкзака или n--мерную задачу раскроя.
    Но ваши ограничения в 10 компонентов позволяют решать эту задачу перебором. Тем более для кулинарии допустимо не слишком упарываться с точностью и ввести квантиикацию компонентов, чтобы иметь дело с целочисленными пропорциями.

    Кстати, я так понимаю, что во всех ингридиентах и результирующем блюде должен быть ещё какой-то специальный ингридиент Z, который будет дополнять выделенные компоненты (например БЖУ) до 100%. Типа инертный наполнитель.
    Допустим у вас есть полный перечень из N доступных ингридиентов. записанных в виде многомерных векторов.
    Вам нужно взять из него подмножество M <= 10 и просуммировать с коэффициентами так, чтобы получилось равенство. Найти нужно x1, x2, x3...x10 - коэффициенты.

    Фактически получится одно векторное уравнение с множеством переменных. А задача сводится к векторному преобразованию из пространства компонентов ингридиентов в подпространство ингридиентов.
    Аналитически такое не решается. Да и точного решения не получится в принципе, поэтому нужно будет придумать как строить норму отклонения от пропорции и минимизировать эту норму.

    Решать можно генетическими алгоритмами или роевыми.
    Фитнес функцией будет норма отклонения от пропорции.
    Ответ написан
  • Как реализовать колоду карт через классы на python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Это у вас вышел совсем плохой варант.
    Классы ради классов. Вообще в первую очередь нужно решать задачу, а не придумывать как бы применить тут наследование или полморфизм.
    В вашем случае лишне сложности ни к чему. Они только добавляют проблем, но ни одной не решают.

    Сделайте карту универсальной, сделайте ее на основе typing.NnamedTuple.
    Пусть у каждой карты будет весь набор атрбутов, но только один какой-то будет ненулевым. Не нужно тут наследования, ведь у вас не используется полиморфизм.

    В вашей реализации не получится сделать две колоды или больше. Колода у вас - это синглтон получается. Такое себе решение.
    На сколько я понмаю предметную область, в колоде важна обычно не столько группировка карт, сколько их порядок. Так и храните карты в инкапсулированном списке.
    Порядок карт не атрибут карт, он должен храниться в колоде.
    Вполне можно держать в инстансе колоды в качестве индекса для быстрой группировки специальный словарь, но это сомнительная оптимизация на таком этапе. Сколько будет в вашей колоде? Является ли вообще бутылочным гордышком проблема группировки? Почему нельзя ее решать на даном этапе просто понятной фильтрацией?
    В общем старайтесь применять новые изученные фичи аккуратно и тоько там, где это на самом деле решает проблемы.
    Интересное упражнение - придумывать пример, где изученная концепция дейтсивтельно к месту. Нследование - это не про ваш вот этот пример с картами. По крайней мере на текущем уровне постановки задачи

    Вот пример:
    import datetime
    import itertools
    from typing import NamedTuple
    
    
    class Card(NamedTuple):
        name: str = None
        phys_damage: int = 0
        hp: int = 0
        mage_damage: int = 0
        armor: int = 0
        add_hp: int = 0
    
        def __repr__(self):
            """repr у нас будет показывать только аргументы, которые отличаются от умолчательных"""
            defaults = type(self)._field_defaults
            params = ', '.join(
                f'{k}={v!r}' 
                for k, v in self._asdict().items() 
                if k in defaults and v != defaults[k]
            )
            return f'{type(self).__name__}({params})'
    
        def __str__(self):
            return f'<{self.name}#{id(self)}>'
            
        @property
        def total_hp(self):
            return self.hp + self.add_hp
    
        @property
        def group(self):
            return max(
                (self.mage_damage, 'Intelegence'),
                (self.add_hp, 'Strength'),
                (self.armor, 'Agility'),
            )[1]
        
    
    class Deck():
        def __init__(self, deck_name="Колода", date=None, cards=None):
            self.deck_name = deck_name
            self.date = date or datetime.now()
            self.cards = cards or []
    
        def __iter__(self):
            return iter(self.cards)
        
        def by_group(self):
            return itertools.groupby(self, lambda card: card.group)
    
    my_deck = Deck("Моя колода", "24.05.2022", [
        Card("Течис", phys_damage=32, hp=600, mage_damage=100),
        Card("Земеля", phys_damage=40, hp=600, mage_damage=60),
        Card("Рудге", phys_damage=80, hp=600, add_hp=150),
        Card("Крип", phys_damage=60, hp=600, armor=10),
    ])
    
    
    for group, cards in my_deck.by_group():
        print(f'# {group}:')
        for card in cards:
            print(f'\t{card!r}')
    Ответ написан
  • Доказано ли, и можно ли сжать произвольные данные до 20 байтов к примеру?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Вы на свой вопрос можете ответить и сами, если посчитаете.
    Произвольные данные не сжимаются. Вообще.
    Доказываем на пальцах. Для детей.
    1. Давайте получим произвольные данные. Для этого возьмём монетку и подбросим 10 раз. Таким образом мы получим 10 бит произвольных данных.
    2. Доказываем, что эти 10 бит нам не сжать даже до 9 бит.
    Сколько всего бывает разных 10-битных последовательностей? Два в степени 10, то есть 1024.
    Сколько всего бывает разных 9-битных последовательностей? Два в степени 9, то есть 512. Это значит, что 9-битным числом можно как-нибудь закодировать только половину произвольных 10-битных последовательностей. Ни одного бита сэкономить не удалось для действительно произвольных (читай случайных) данных.

    -- А как же работают архиваторы? - спросите вы.
    А архиваторы сжимают не произвольные данные, а какие-то осмысленные. Осмысленных данных меньше чем любых. Это очевидно. Вот архиваторы этим и пользуются.
    Давайте пример. Допустим наша "монетка" умеет падать не на две стороны, а на три. Ну циллиндрик такой. толстенький, который частенько падает на ребро. И мы его подбросили пять раз, но хотим почему-то записать полученную последовательность в вдоичной форме. Очевидно, что двумя значениями 1 и 0 мы не можем закодировать три стороны "монетки" (назовём её тринеткой). А два бита может кодировать уже четыре разных состояния: 00, 01, 10, 11. Нам хватит трёх из них, а четвертое, скажем 11, пусть будет ненужным.
    Тогда 5 бросков тринетки мы можем записать 10 двоичными битами. Но данных в этих 10 битах будет на самом деле храниться только 3 в степени 5 = 3*3*3*3*3=243. То есть 243 состояния тринетки кодируются 10 битами, в которые помещается на самом деле 1024 разных произвольных значений.
    Это как раз и есть то место, где можно успешно сжать данные.

    А насколько можно сжать? Давайте считать. 8 бит может представить 2*2*2*2*2*2*2*2=256 разных произвольных значений. А нам надо 243. Это значит, что любые 5 бросков тринетки мы можем закодировать не 10-ю битами, а всего лишь 8-ю. Сэкономили два бита, но больше сэкономить не получится ни одного бита!

    А откуда ж берутся огромные коэффициенты сжатия? Например тексты на человеческих языках довольно неплохо сжимаются. А всё просто. Мы кодировали каждый бросок тринетки для простоты 2-мя битами, и там одно сочетание было нам не нужно. А представьте, если бы нам не хотелось бы возиться с битами и мы посчитаи более простым хранить броски тринетки каждый в одном байте!
    То есть нам бы хватило и 2 бит слихвой, но м ырешили на каждый бросок использовать 8 только потому, что у нас компьютеры не сильно приспособлены быстро работать с более мелкими кусками данных.
    Получается, что 5 бросков тринетки мы закодируем в 8*5байт=40бит, а мы уже уяснили что и 10 бит хватило бы, и даже 8, но никак уж не меньше восьми.
    Получается, что расточительную 40-битную запись пяти бросков тринетки мы могли бы сжать аж в 5 раз до 8 бит! То есть мы используем 5 байт там, где хватило бы одного, вот и получилось, что можно сделать сжатие.

    Также и маленький рандомный сид может кодировать террабайтные миры в играх. Но соль в том, что миров этих разных получится ровно столько. сколько значений сида может быть. Мы просто в террабайтах храним мир в очень неэффективной но удобной для использования форме.

    Расписал как мог просто. Если у вас после этого остались иллюзии, что можно сжать гигабайтный фильм до одного байта, а потом распаковать его обратно, то вам уже ничто не поможет. Потому что фильмов человечество наснимала уже гораздо больше 256, а значений одного байта всего как раз столько.
    Вы можете написать архиватор, который будет сжимать произвольный фильм из ваших любимых 256 фильмов. Но при этом сам архиватор будет размером 256 гигабайт, а байт будет просто номером в библиотеке ваших любимых фильмов. Но да, вполне реально назвать вашему другу по телефону тремя байтами три любых фильма из вашей общей коллекции, а у друга на винте такой же "архиватор", как бы, "распакует" эти числа в целые три фильма, которые на самом деле и так уже были у друга.

    Других чудес не бывает.
    Ответ написан
  • Как расчитать координаты точек для шестиугольника вписанного в круг?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    А мне нравится такое на комплексных числах считать. То же, что и с синусами, но элегантнее.
    Вот пример на питоне:
    from math import e, pi
    f=lambda c, r, n=3, fi0=0: [c+r*e**(1j*(2*pi/n*i+fi0)) for i in range(n)]

    Получим функцию f которая может рассчитать точки любого вписанного n-угольника:
    >>> f(c=250+250j, r=250)
    [(500+250j),
     (375+466.50635094610965j),
     (125.00000000000006+466.5063509461097j),
     250.00000000000003j,
     (124.99999999999989+33.49364905389041j),
     (374.99999999999983+33.49364905389024j)]

    А если надо обяательно кортежами, а не комплексными точками. то вот:
    >>> [(round(p.real), round(p.imag)) for p in f(c=250+250j, r=250, n=5, fi0=pi/2)]
    [(250, 500), (12, 327), (103, 48), (397, 48), (488, 327)]

    Тут, заметьте, пятиугольник, причем вершинкой вниз (при оси Y, направленной вниз).

    Чтобы было понятно как это работает...
    Представим, что центр окружности в нуле координат. Нам нужно 6 точек, смещенных относительно нуля на радиус под нужными углами: 0, 60, 120, 180, 240 и 300 градусов. В формулах мы. конечно используем радианы: pi - это 180 градусов.
    Чтобы повернуть единичный вектор на какой-то угол, нужно его просто домножить на e в степени мнимая единица, умноженная на угол. Поскольку единичный вектор на комплексной плоскости это просто 1, то его даже писать не надо. Просто возводим e в нужную степень и получаем нужный вектор в виде комплексного числа. Осталось его домножить на требуемый радиус (он при этом удлинится: был длиной 1, а станет r) и добавить к нему желаемый центр (тоже в виде комплексного числа, где реальная часть - X, а мнимая - Y).
    Вот и всё!
    Красота же?..

    Да, забыл сказать, что если нужно повернуть весь n-угольник на какой-то угол, то для этого есть там параметр fi0, который по умолчанию ноль.
    c - это координаты центра в комплексной форме. Например если X=30, а Y=40, то c=30+40j.
    n - это число вершин.
    r - радиус.
    И да, в javascript'е нет такого элегантного способа работать с комплексными числами, как в питоне. Но для js есть много библиотек для работы с комплексными числами. Будет не так компактно и красиво, как на питоне, но в целом всё точно так же в плане математики.

    UPD: Исправил функцию. Там скобочек не хватало, поэтому поворот на fi0 работал неверно. Теперь все как надо.
    Ответ написан
    6 комментариев
  • Почему не работает?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Потому что иногда поиск что-то находт и дает результат, а ногда не находит и возвращает None
    Ответ написан
    3 комментария
  • Есть ли такой бот?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Нет такого бота, и на тех возможностях, которые предоставляет API такого нельзя реализовать.
    Ответ написан
  • Порядковый генератор фразы?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Это делается так:
    itertools.product(*[words] * len(words))
    Но вам, похоже, рано решать такие задачи, ведь вы совсем не знаете язык. Да и задания на этом ресурсе против правил. Лучше изучайте питон, а не жульничайте тут с решением задач.

    UPD:
    А можно и вот так вот рекурсивно:
    def r(w=words, n=5): 
        if n > 1: 
            yield from ([i] + rr for i in w for rr in r(w=w, n=n-1)) 
        else: 
            yield from ([i] for i in w)

    Максимальная глубина рекурсии - n
    Ответ написан
    3 комментария
  • Как сделать правильно?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    pogoda = pogoda.replace(' ', '-')
    Или в чем проблема?
    Ответ написан
  • Как составить регулярку с батником?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    А зачем тут регекспы? Отличаться-то будет только искомая подстрока. Отрезайте нужное количество символов по бокам и всё.
    Ещё в батниках есть синтаксис. который позволяет заменять подстроку:
    set str="any_text/UC5qUbVE66mMu9kvsn_ki5yQ"
    set str=%str:any_text=%

    Чтобы заменить конкретный кусок урла, придётся экранировать символы, но попробовать мне негде, вокруг нет винды, так что экспериментируйте.

    UPD:
    После разъяснения автором стало понятнее. Вот решение:
    py -x "'channel/'+x.split('/')[5]" < t1.txt > t2.txt

    Утилита py стандартная, ставится в рамках пакета pythonpy, удобна для конвейерной обработки питоновскими однострочниками файловых потоков.
    Ответ написан
    6 комментариев
  • Как сделать плейлист?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    В ffmpeg можно послать целый текстовый плейлист через ключ -i, можно дописывать линки в файл плейлиста. Вопрос только втом, будет ли ffmpeg его подхватывать по факту изменения.
    Ответ написан
    Комментировать
  • Как упростить SQL запрос?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Что-то у меня дежавю. Недавно вы с похожим вопросом сюда приходили.
    Не задания ли это для какого-нибудь теста?
    Да и вам намекали, что отвечать на такие вопросы удобнее, если вы не вот эту хрень рисуете в описании таблиц, а sql-дамп метаданных приводите. Там видно и ключи, и ссылки, и индексы. Да и выполнить такой SQL для эксперимента можно мгновенно. А вы игнорируете рекомендации.

    Такого рода сортировки по сложным сложных джойнам и на довольно больших объёмах быстро работать не будут. Такие вещи решают денормализацией.
    Можно сделать отдельную аггрегированную таблицу, которая будет 1к1 джойниться к вашей тблице продуктов и предоствлять уже посчитанные данные.

    Такую таблицу считают первично один раз и на это не жалко 350с, а потом её можно поддерживать в акутальном состоянии триггерами или допилив бэкенд. Всё таки запись в аггрегируемые таблицы по времени не так критична обычно, как выборка этой статистики.
    Ответ написан
  • Как через python узнать кто подключался к твоему wifi?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Самый простой вариант - это забирать с ротуера логи и из них забирать инфу о подключении. Если это ваша сеть, то и настройки роутера вам доступны, а значит вы можете их анализировать.
    Если по какой-то причине нет возможности получать логи с роутера, то можно периодически сканировать локалку на предмет поиска новых компьютеров. Не важно на каком языке вы будете обрабатывать выхлоп утилит вроде nmap. Как этой и аналогичными утилитами просканировать сеть - это отдельный вопрос.
    В самом простом слуае вы можете написать на питоне утилиту, парсящую выхлоп nmap и перечень IP и mac-адресов кладущую в sqlite или тупо дописывающую в csv. Отдельной утилитой можно фильтровать получившийся журнал за указанные интервалы времени.
    Ответ написан
    Комментировать
  • Как упростить запрос sql?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    SELECT  
        p.*, 
        (SELECT COUNT(op.count) FROM orders_products op WHERE op.product_id = p.id) AS countorders
    FROM    products p
    ORDER BY p.id ASC
    LIMIT 25

    Нужно убедиться, что на op.product_id есть индекс, а лучше foreign key, чтобы еще и целостность данных соблюдалась автоматически.
    В таком виде и с таким ограничением при наличии упомянутого индекса запрос должен занимать миллисекунды
    Ответ написан
    Комментировать