Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Скриптовые языки программирования > Python
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.11.2023, 09:48   #1
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию Сортировка списка - удалить частичные повторы

здравствуйте, как сделать по сабжу я в курсе
Код:
a = ["5q5", "7", "66", "77", "5", "6", "36", "9"] # сортировка списка - удалены частичные повторы
print(*filter(lambda i: all(map(lambda x: i not in x, [x for x in a if x != i])), a))  # 5q5 66 77 36 9
так и не понял как создать новый список b, чтобы он был равен ["5q5", "66", "77", "36", "9"]?
спасибо
Ципихович Эндрю вне форума Ответить с цитированием
Старый 02.11.2023, 09:59   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Код:
b = list(filter(...))
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 02.11.2023, 10:11   #3
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

ок, то, что нужно:
Код:
a = ["5q5", "7", "66", "77", "5", "6", "36", "9"] # сортировка списка - удалены частичные повторы
b = list(filter(lambda i: all(map(lambda x: i not in x, [x for x in a if x != i])), a))
print(b)  # ['5q5', '66', '77', '36', '9']
Ципихович Эндрю вне форума Ответить с цитированием
Старый 03.11.2023, 08:08   #4
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

2 вариант
Код:
a = ["5q5", "7", "66", "77", "5", "6", "36", "9"]
b = [x for x in a if x not in [x for x in a for y in a if x != y and x in y]]
print(b)
скажите какой из этих двух вариантов более быстрый?
со списком размера примерно
758177
реально дождаться обработки? что-то мой ПК конца и края не видит..........
Ципихович Эндрю вне форума Ответить с цитированием
Старый 03.11.2023, 23:43   #5
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Из этих двух вариантов быстрее третий (чуть измененный второй):
Код:
import timeit

for code in [
    '''\
a = ["5q5", "7", "66", "77", "5", "6", "36", "9"]
b = list(filter(lambda i: all(map(lambda x: i not in x, [x for x in a if x != i])), a))
''',
    '''\
a = ["5q5", "7", "66", "77", "5", "6", "36", "9"]
b = [x for x in a if x not in [x for x in a for y in a if x != y and x in y]]
''',
    '''\
a = ["5q5", "7", "66", "77", "5", "6", "36", "9"]
c = [x for x in a for y in a if x != y and x in y]
b = [x for x in a if x not in c]
'''
]:
    #print(code)
    #exec(code + "\nprint(b)")
    print(timeit.timeit(code, number = 10000))
Код:
0.13180309999999998
0.36127600000000004
0.048267199999999955
Цитата:
Сообщение от Ципихович Эндрю Посмотреть сообщение
реально дождаться обработки
Вот с таким примером на моем ПК время на обработку списка из 750000 элементов можно грубо оценить в 19 часов.
Код:
import timeit
import string

def NumToStr(num):
    result = []
    letters = string.ascii_lowercase
    letters_len = len(letters)
    while num:
        num, rem = divmod(num - 1, letters_len)
        result[:0] = letters[rem]
    return ''.join(result)

s = '''\
c = [x for x in a for y in a if x != y and x in y]
b = [x for x in a if x not in c]
'''
for c in [10, 100, 500, 1000, 5000, 10000]:
    a = [NumToStr(i) for i in range(1, c + 1)]
    print(c, timeit.timeit(s, number = 1, globals = globals()))
Код:
10 7.80000000000225e-06
100 0.0006367999999999929
500 0.017754900000000018
1000 0.09059660000000003
5000 2.792164
10000 10.9601953
UPD. Вот такой "велосипед" справляется с миллионом элементов за 3 секунды, но что будет на реальных данных, не могу угадать.
Код:
import timeit
import string
from collections import defaultdict 

def NumToStr(num):
    result = []
    letters = string.ascii_lowercase
    letters_len = len(letters)
    while num:
        num, rem = divmod(num - 1, letters_len)
        result[:0] = letters[rem]
    return ''.join(result)

def filter_f(a):
    d = defaultdict(list)
    res = []
    known_ws = set()
    for w in a:
        d[len(w)].append(w)
    lens = sorted(d.keys(), reverse = True)
    for i, k in enumerate(lens):
        for w in d[k]:
            if w not in known_ws:
                res.append(w)
                known_ws.add(w)
                for l in lens[i + 1:]:
                    for s in range(k - l + 1):
                        known_ws.add(w[s:s + l])
    return res

s = '''\
c = [x for x in a for y in a if x != y and x in y]
b = [x for x in a if x not in c]
'''
for c in [10, 100, 500, 1000, 5000, 10000]:
    a = [NumToStr(i) for i in range(1, c + 1)]
    print(c,
        timeit.timeit(s, number = 1, globals = globals()),
        timeit.timeit("filter_f(a)", number = 1, globals = globals())
    )

for c in [50000, 100000, 500000, 1000000]:
    a = [NumToStr(i) for i in range(1, c + 1)]
    print(c,
        timeit.timeit("filter_f(a)", number = 1, globals = globals())
    )
Код:
10 8.2e-06 1.579999999999999e-05
100 0.0006411000000000001 0.0001049
500 0.018240100000000002 0.0005647999999999972
1000 0.0822098 0.0018729999999999997
5000 2.8664011 0.00890039999999992
10000 11.7256719 0.019374099999998506
50000 0.1307482000000011
100000 0.3265539999999998
500000 1.8473674999999972
1000000 2.9146336999999995
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 04.11.2023 в 01:04.
BDA вне форума Ответить с цитированием
Старый 04.11.2023, 09:19   #6
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

BDA, спасибо, пока удалил лишнее, связанное с тестом:
Код:
from collections import defaultdict
 
def filter_f(a):
    d = defaultdict(list)
    res = []
    known_ws = set()
    for w in a:
        d[len(w)].append(w)
    lens = sorted(d.keys(), reverse = True)
    for i, k in enumerate(lens):
        for w in d[k]:
            if w not in known_ws:
                res.append(w)
                known_ws.add(w)
                for l in lens[i + 1:]:
                    for s in range(k - l + 1):
                        known_ws.add(w[s:s + l])
    return res
вывод
['5q5', '7', '66', '77', '5', '6', '36', '9']
['5q5', '66', '77', '36', '9']
опробую))
Ципихович Эндрю вне форума Ответить с цитированием
Старый 04.11.2023, 12:32   #7
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

на моих реальных данных скрипт падает на строке
Код:
known_ws.add(w[s:s + l])
MemoryError
Ципихович Эндрю вне форума Ответить с цитированием
Старый 04.11.2023, 14:26   #8
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

Цитата:
Сообщение от Ципихович Эндрю Посмотреть сообщение
на моих реальных данных скрипт падает на строке
Код:
known_ws.add(w[s:s + l])
MemoryError
понял свою ошибку, разберусь..........
Ципихович Эндрю вне форума Ответить с цитированием
Старый 07.11.2023, 03:00   #9
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Цитата:
Сообщение от Ципихович Эндрю Посмотреть сообщение
MemoryError
Вот такой вариант, вроде, должен меньше памяти тратить:
Код:
def filter_f2(a):
    d = defaultdict(set)
    res = set(a)
    for w in a:
        d[len(w)].add(w)
    lens = sorted(d.keys(), reverse = True)
    for i, k in enumerate(lens):
        for w in d[k]:
            if w in res:
                for l in lens[i + 1:]:
                    for s in range(k - l + 1):
                        ww = w[s:s + l]
                        if ww in res:
                            res.remove(ww)
    return list(res)
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 08.11.2023, 08:25   #10
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

ок, опробую:
Код:
a = ["5q5", "7", "66", "77", "5", "6", "36", "9"]
from collections import defaultdict
def filter_f2(a):
    d = defaultdict(set)
    res = set(a)
    for w in a:
        d[len(w)].add(w)
    lens = sorted(d.keys(), reverse = True)
    for i, k in enumerate(lens):
        for w in d[k]:
            if w in res:
                for l in lens[i + 1:]:
                    for s in range(k - l + 1):
                        ww = w[s:s + l]
                        if ww in res:
                            res.remove(ww)
    return list(res)
print(filter_f2(a))
Ципихович Эндрю вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
удалить повторы со сложением значений Вячеслав76 Microsoft Office Excel 2 20.01.2021 11:16
Удалить повторы из списка mazzahaker Общие вопросы C/C++ 0 21.04.2012 22:34
удалить повторы в таблице Радужок Microsoft Office Excel 2 30.04.2011 20:37
Удалить повторы строк Federal Помощь студентам 16 27.02.2011 02:37
удалить повторы FAiver Общие вопросы Delphi 5 21.10.2010 20:45