Есть ли более эффективный способ переписать несколько операторов if-else - PullRequest
1 голос
/ 08 мая 2019

Я хочу спросить, есть ли более эффективный и правильный способ переписать мой следующий код (просто потому, что существует много операторов if-else)

key_list в следующем является списком списков, каждый из которых содержит несколько оснований ДНК, например, key_list = [['-'], ['A'], ['A', 'T'], ['C', 'G', 'T']] и '-' используется для представления специального пробела .

У меня возникла идея использовать словарь для построения отношений отображения между этими утверждениями, но не настолько уверен в правильности.

output = []
for l in key_list:
    if len(l) == 1:
        output.append(l[0])
    elif len(l) == 2:
        if set(l) == set(['A', 'G']):
            output.append('R')
        elif set(l) == set(['C', 'T']):
            output.append('Y')
        elif set(l) == set(['A', 'C']):
            output.append('M')
        elif set(l) == set(['G', 'T']):
            output.append('K')
        elif set(l) == set(['G', 'C']):
            output.append('S')
        elif set(l) == set(['A', 'T']):
            output.append('W')
        else:
            print('Error!')
    elif len(l) == 3:
        if set(l) == set(['A', 'T', 'C']):
            output.append('H')
        elif set(l) == set(['G', 'T', 'C']):
            output.append('B')
        elif set(l) == set(['A', 'G', 'C']):
            output.append('V')
        elif set(l) == set(['A', 'T', 'G']):
            output.append('D')
        else:
            print('Error!')
    elif len(l) == 4:
        output.append('N')
    else:
        output.append('-')  # if there is only '-' in the column, also add it.

1 Ответ

2 голосов
/ 08 мая 2019

вы можете использовать tuple(sorted(set(l))) для создания ключа для словаря:

elif len(l) == 2 or len(l) == 3:
    key = tuple(sorted(set(l)))
    output.append(lookup_dict[key])

где lookup_dict это что-то вроде:

lookup_dict = {('A', 'G') : 'R',
      ('C', 'T') : 'Y',
      ('A', 'C'): 'M',
      ('A', 'C', 'T') : 'H',   # note that it's A,C,T, not A,T,C, sort order!

 }

... и т. Д. (Объединение обоих случаев длины 2 и 3)

Примечания:

  • кортежи отсортированы в алфавитном порядке или tuple(sorted(set(l))) не будет соответствовать. tuple требуется преобразование, поэтому ключи можно хэшировать (list не подходит)
  • благодаря словарю сложность поиска уменьшена с O(n) с вашим методом (плюс бесполезное и многократное set создание) до O(1).
  • код не обрабатывает случай "ошибки". Если совпадения нет, вы получите KeyError, вероятно, лучше, чем print('Error!'). Если вы хотите проверить сначала, используйте key in lookup_dict условие.

Как предлагается в комментариях, frozenset также может использоваться как ключ словаря. В этом случае код проще:

elif len(l) == 2 or len(l) == 3:
    key = frozenset(l)
    output.append(lookup_dict[key])

и lookup_dict требуется дополнительная предварительная обработка для преобразования ключей в тип frozenset (но не требуется сортировка ключевых элементов, что менее подвержено ошибкам):

lookup_dict = {frozenset(k):v for k,v in lookup_dict.items()}

Но после этого решение, вероятно, будет немного быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...