Существует ли более эффективный подход для проверки строки в списке, избегая (слегка) измененных дубликатов?

#python #string #list

#python #строка #Список

Вопрос:

Проблема со слегка измененными строками в списке при проверке по отсортированному списку строк.

Я проверяю строки, представляющие содержимое из некоторых файлов. И у меня есть список определенных строк, которые я проверяю, однако иногда в конце одной и той же строки может быть добавлена звездочка (*), что приводит к слегка измененным дубликатам в этом списке.

В настоящее время:

   # This is minimal very minimal code example: 
  for _word in sorted(['Microsoft','Microsoft*']): 
      print(_word)
  

Желаемый:

 for _word in sorted(['Microsoft']):
    print(_word)

 # But still be able to check for 'Microsoft*' without having duplicates in the list.
  

Окончательное решение:

 import os
import sys

if __name__ == '__main__':

    default_strings = sorted([
        'microsoft',
        'linux',
        'unix',
        'android'
    ])

    text = str("""
        Microsoft* is cool, but Linux is better. 
     """)

    tokens = text.split(" ")
    for token in tokens:
        token = token.lower()
        if token.endswith('*'): 
            token = token[:-1]

        if token in default_strings:
            print(token)
  

РЕДАКТИРОВАТЬ: Если есть способ получше, пожалуйста, дайте мне знать. Большое спасибо всем, кто участвовал и откликнулся.

Комментарии:

1. фильтруйте специальные символы и используйте set вместо list.

2. Нет, наборы здесь не работают. Я протестировал sets() и {} dictionary.

3. да, но можете ли вы сначала отфильтровать специальные символы, а затем преобразовать их в set?

4. Просто определите свой собственный, MySet расширив встроенный set класс, а затем измените метод двойного подчеркивания, где проверка дублирования будет игнорировать специальные символы, такие как звездочка (*). Наконец, приведите свой список к типу MySet.

Ответ №1:

Основываясь на моем комментарии; Если вы не хотите использовать set, тогда,

 my_filters = ['*']
my_list = ['Microsoft','Microsoft*']
final_list = [ x.replace(y,'')  for x in my_list for y in my_filters if y in x ]
  

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

Комментарии:

1. @JohnSmith в каком смысле это неэффективно? Предложенное вами решение столь же эффективно, за исключением того, что ваше default_strings должно быть set , иначе оба этих подхода будут квадратичными по времени. Редактировать: и зачем их сортировать?

2. @JohnSmith преобразование в set — это единовременная предварительная стоимость. Но если вы собираетесь проверять членство много раз , то набор определенно более эффективен . Кроме того, поиск по отсортированному списку выполняется быстрее, только если вы используете двоичный поиск , но вы этого не делаете. Просто используй set, чувак, это именно то, для чего они предназначены . Кроме того, если вы можете «вручную определить» свой список, вы можете просто сделать это с помощью set . Не учитывайте время создания в своих таймингах. Опять же, set объекты устраняют дубликаты, но это не их цель, их назначение быстрое тестирование членства

3. @JohnSmith gist.github.com/juanarrivillaga / … просто посмотрите на тайминги. Да, загрузка набора изначально будет стоить дороже , но если вы собираетесь использовать набор для тестирования членства, тогда это будет намного быстрее . Я не думаю, что вы понимаете разницу между этими структурами данных, это основной вариант использования set . Кроме того, любые накладные расходы на создание набора будут сведены к минимуму, если вы затем будете сортировать список. Обратите внимание, проверка membershipt в наборе постоянно длится около 25 наносекунд, не имеет значения, содержит ли он один элемент или 1000 элементов.

4. @JohnSmith с другой стороны, к тому времени, когда вы проверяете элемент в списке из 1000 элементов, это занимает 12 микросекунд, что примерно в 500 раз быстрее с набором . И прелесть в том, что вы будете продолжать замедляться по мере увеличения списка, но он будет оставаться неизменным независимо от размера набора

5. @JohnSmith да, set объекты существуют для проверки членства . Это их основная цель существования. Если вам нужно выполнить итерацию по чему-либо, list будет самой быстрой встроенной структурой данных python для этого.