Разрешить удаление определенных подстрок различной длины из строк - PullRequest
2 голосов
/ 17 апреля 2019

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

AlCrHfMoNbN
AlCrHfMoTaN
AlCrHfMoTiN
AlCrHfMoVN
AlCrHfMoWN
...

Я пытаюсь получить

 AlCrHfMoNbN --> CrHfMoNbN
                 AlHfMoNbN
                 AlCrMoNbN
                 AlCrHfNbN
                 AlCrHfMoN
AlCrHfMoTaN -->  CrHfMoTaN
                 AlHfMoTaN
                 AlCrMoTaN
                 AlCrHfTaN
                 AlCrHfMoN

для каждой композиции.Мне просто нужен правильный столбец.Как видите, некоторые из полученных композиций являются дубликатами, и это предназначено.Список элементов, которые необходимо удалить:

Al, Cr, Hf, Mo, Nb, Ta, Ti, V, W, Zr

Как видите, некоторые имеют длину два символа, а некоторые только один.

Есть вопрос, который задает что-то очень похожее, однако моя проблема более сложна: Получение списка строк с символом, удаленным в перестановке

Я попытался настроитькод для моих нужд:

def f(s, c, start):
    i = s.find(c, start)
    return [s] if i < 0 else f(s, c, i+1) + f(s[:i]+s[i+1:], c, i)

s = 'AlCrHfMoNbN'
print(f(s, 'Al', 0))

Но этот простой подход приводит только к ['AlCrHfMoNbN', 'lCrHfMoNbN'].Таким образом, удаляется только один символ, тогда как мне нужно удалить определенную строку символов различной длины.Кроме того, я ограничен одним входным объектом s - вместо сотен, которые мне нужно обработать - поэтому циклический переход вручную не возможен.


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

  • ввести список строк, разделенных переносами строк или пробелами
  • удалить из этого списка подстроки символов, которые определены вторым списком (простокак указано выше)
  • записывает результирующие «уменьшенные» элементы в непрерывном списке, предпочтительно в виде одного столбца без запятых, например

Поскольку у меня есть только некоторый опыт работы с Python и Bash IНастоятельно предпочитаю решение с этими языками.

Ответы [ 3 ]

3 голосов
/ 17 апреля 2019

IIUC, все что вам нужно это str.replace:

input_list = ['AlCrHfMoNbN', 'AlCrHfMoTaN']
removals = ['Al', 'Cr', 'Hf', 'Mo', 'Nb', 'Ta', 'Ti', 'V', 'W', 'Zr']
result = {}
for i in input_list:
    result[i] = [i.replace(r,'') for r in removals if r in i]    

Выход:

{'AlCrHfMoNbN': ['CrHfMoNbN',
  'AlHfMoNbN',
  'AlCrMoNbN',
  'AlCrHfNbN',
  'AlCrHfMoN'],
 'AlCrHfMoTaN': ['CrHfMoTaN',
  'AlHfMoTaN',
  'AlCrMoTaN',
  'AlCrHfTaN',
  'AlCrHfMoN']}
1 голос
/ 17 апреля 2019

если у вас есть gawk, установите FPAT на [A-Z][a-z]*, чтобы каждый элемент рассматривался как поле, и используйте простой цикл для генерации перестановок.также установите для OFS пустую строку, чтобы в выходных записях не было пробелов.

$ gawk 'BEGIN{FPAT="[A-Z][a-z]*";OFS=""} {for(i=1;i<NF;++i){p=$i;$i="";print;$i=p}}' file
CrHfMoNbN
AlHfMoNbN
AlCrMoNbN
AlCrHfNbN
AlCrHfMoN
CrHfMoTaN
AlHfMoTaN
AlCrMoTaN
AlCrHfTaN
AlCrHfMoN
CrHfMoTiN
AlHfMoTiN
AlCrMoTiN
AlCrHfTiN
AlCrHfMoN
CrHfMoVN
AlHfMoVN
AlCrMoVN
AlCrHfVN
AlCrHfMoN
CrHfMoWN
AlHfMoWN
AlCrMoWN
AlCrHfWN
AlCrHfMoN

Я также написал переносимый файл с дополнительными пробелами и пояснительными комментариями:

awk '{
  # separate last element from others
  sub(/[A-Z][a-z]*$/, " &")
  # from the beginning of line
  # we will match each element and print a line where it is omitted
  for (i=0; match(substr($1,i), /[A-Z][a-z]*/); i+=RLENGTH)
    print substr($1,1,i)  substr($1,i+RLENGTH+1) $2
    #     ^ before match  ^ after match          ^ last element
}' file
0 голосов
/ 17 апреля 2019

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

def f(s):
    # split string by elements
    import re
    elements = re.findall('[A-Z][^A-Z]*', s)

    # make a list of strings, where the first string has the first element removed, the second string the second, ...
    r = []
    for i in range(len(elements)):
        r.append(''.join(elements[:i]+elements[i+1:]))

    # return this list
    return r

Конечно, это все еще толькоработает на одну строку.Так что, если у вас есть список строк l, и вы хотите применить его для каждой строки в нем, просто используйте цикл for следующим образом:

# your list of strings
l = ["AlCrHfMoNbN", "AlCrHfMoTaN", "AlCrHfMoTiN", "AlCrHfMoVN", "AlCrHfMoWN"]

# iterate through your input list
for s in l:
    # call above function
    r = f(s)
    # print out the result if you want to
    [print(i) for i in r]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...