У меня есть следующий список предметов.

items_list=[ '$', '^', '#', '(', ')', '-', '.', '/', '1', '2', '3', '4', '5', '6', '7', '=', 'Br', 
           'C', 'Cl', 'F', 'I', 'N', 'O', 'P', 'S', '[2H]', '[Br-]', '[C@@H]', '[C@@]', '[C@H]', '[C@]', 
           '[Cl-]', '[H]', '[I-]', '[N+]', '[N-]', '[N@+]', '[N@@+]', '[NH+]', '[NH2+]', '[NH3+]', '[N]', 
           '[Na+]', '[O-]', '[P+]', '[S+]', '[S-]', '[S@+]', '[S@@+]', '[SH]', '[Si]', '[n+]', '[n-]', 
           '[nH+]', '[nH]', '[o+]', '[se]', '\\', 'c', 'n', 'o', 's', '!', 'E']

И моя строка как под.

string='N[C@H]1C[C@@H](N2Cc3nn4cccnc4c3C2)CC[C@@H]1c1cc(F)c(F)cc1F'

Есть ли какой-нибудь питонический способ найти длину этого string на основе элементов в items_list?

Объяснение:

N следует рассматривать как один символ, как и [C@H], потому что оба они представлены как отдельные элементы в списке словаря.

2
Abdul Karim Khan 21 Авг 2020 в 07:52

3 ответа

Лучший ответ

Вы можете использовать re.findall после экранирования токенов как регулярного выражения:

import re

items_list=[ '$', '^', '#', '(', ')', '-', '.', '/', '1', '2', '3', '4', '5', '6', '7', '=', 'Br', 
           'C', 'Cl', 'F', 'I', 'N', 'O', 'P', 'S', '[2H]', '[Br-]', '[C@@H]', '[C@@]', '[C@H]', '[C@]', 
           '[Cl-]', '[H]', '[I-]', '[N+]', '[N-]', '[N@+]', '[N@@+]', '[NH+]', '[NH2+]', '[NH3+]', '[N]', 
           '[Na+]', '[O-]', '[P+]', '[S+]', '[S-]', '[S@+]', '[S@@+]', '[SH]', '[Si]', '[n+]', '[n-]', 
           '[nH+]', '[nH]', '[o+]', '[se]', '\\', 'c', 'n', 'o', 's', '!', 'E']

string='N[C@H]1C[C@@H](N2Cc3nn4cccnc4c3C2)CC[C@@H]1c1cc(F)c(F)cc1F'

pattern = '|'.join(re.escape(item) for item in items_list)
tokens = re.findall(pattern, string)
print(len(tokens))

Здесь tokens будет списком:

['N', '[C@H]', '1', 'C', '[C@@H]', '(', 'N', '2', 'C', 'c', '3', 'n', 'n', '4', 'c', 'c', 'c', 'n', 'c', '4', 'c', '3', 'C', '2', ')', 'C', 'C', '[C@@H]', '1', 'c', '1', 'c', 'c', '(', 'F', ')', 'c', '(', 'F', ')', 'c', 'c', '1', 'F']

Так что длина 44.

Обратите внимание, что | здесь означает «или».

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

re.match(f'({pattern})*$', string)

Если этого не произойдет, у вас будет None вместо совпадения.

2
alani 21 Авг 2020 в 05:09

Не уверен, что он достаточно питонический, но вот оно:

symbols = set(items_list)
size=0
start=0

while start<len(string):
    end=start+1
    while end<=len(string):
        if string[start:end] in symbols:
            print(string[start:end])
            size+=1
            start=end-1
            break
        end+=1
    start+=1

print(size)

44

2
Thiago Curvelo 21 Авг 2020 в 05:41

Итак, я предполагаю, что вы имеете в виду, что хотите найти количество символов в строке, которые также есть в вашем списке. Цикл for должен делать это:

items_list = [ '$', '^', '#', '(', ')', '-', '.', '/', '1', '2', '3', '4', '5', '6', '7', '=', 'Br', 
             'C', 'Cl', 'F', 'I', 'N', 'O', 'P', 'S', '[2H]', '[Br-]', '[C@@H]', '[C@@]', '[C@H]', '[C@]', 
             '[Cl-]', '[H]', '[I-]', '[N+]', '[N-]', '[N@+]', '[N@@+]', '[NH+]', '[NH2+]', '[NH3+]', '[N]', 
             '[Na+]', '[O-]', '[P+]', '[S+]', '[S-]', '[S@+]', '[S@@+]', '[SH]', '[Si]', '[n+]', '[n-]', 
             '[nH+]', '[nH]', '[o+]', '[se]', '\\', 'c', 'n', 'o', 's', '!', 'E'];

length = 0;
string = 'N[C@H]1C[C@@H](N2Cc3nn4cccnc4c3C2)CC[C@@H]1c1cc(F)c(F)cc1F';
count = 0;

for i in string: # Annoyingly, Python only has foreach statements...
    if (string[count] in items_list): # If this letter is in your list:
        length += 1; # Length is one more
    if (count > len(items_list) + 1): # If we have two letters to work with:
        if ((string[count] + string[count + 1]) in items_list): # If the next two letters added together is an item in your list:
            length += 1; # Length is one more
            count +=  1; # Skip the next two letters
        if (count > len(items_list) + 2): # Same as above for three letters:
            if ((string[count] + string[count + 1] + string[count + 2]) in items_list):
                length += 1;
                count +=  2;
            if (count > len(items_list) + 3): # Same as above but for four letters:
                if ((string[count] + string[count + 1] + string[count + 2] + string[count + 3]) in items_list):
                    length += 1;
                    count +=  3;
                if (count > len(items_list) + 4): # And five:
                    if ((string[count] + string[count + 1] + string[count + 2] + string[count + 3] + string[count + 4]) in items_list):
                        length += 1;
                        count +=  3;
    count+= 1;
    
print(length);

Это дало мне результат 44.

0
Kettle3D 21 Авг 2020 в 05:18