从字符串中置换删除长度可变的已定义子字符串

2024-09-28 23:37:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图从一个字符串列表中生成所有排列,其中某些字符的子字符串被删除。我有一个特定化学成分的列表,我想要从列表中删除其中一个元素的所有成分。此列表的简短摘录如下所示:

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

正如你所看到的,有些有两个字符的长度,有些只有一个字符。你知道吗

有一个问题问的东西非常相似,但我的问题更复杂: Getting a list of strings with character removed in permutation

我试着根据自己的需要调整代码:

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只有一些经验,所以我非常喜欢使用这些语言的解决方案。你知道吗


Tags: 对象字符串代码元素列表定义字符start
3条回答

如果您有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

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']}

这并不使用您的尝试,但当我们假设您的元素总是以大写字母开头(否则仅由小写字母组成)时,它就起作用了:

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]

相关问题 更多 >