【问题标题】:String replacement combinations with fixed parts带固定部件的换弦组合
【发布时间】:2017-06-04 00:56:18
【问题描述】:

假设我有以下字符串 abcixigea,我想用 '1'、'3' 和 '4' 替换第一个 'i'、'e' 和第二个 'a' ,获得所有与那些“渐进式”替换的组合。

所以,我需要得到:
abc1xigea
abcixig3a
abcixig34
abc1xige4
...等等。

我在这个问题python string replacement, all possible combinations #2 之后尝试使用 itertools.product,但我得到的结果并不完全符合我的需要,我知道为什么。
但是我坚持尝试组合并保持部分字符串固定(如上所述仅更改一些字符)。

【问题讨论】:

  • 当您说“第一次”出现时,您是从左到右扫描吗?在您的示例中,为什么要替换第二个“a”?
  • 抱歉,我忘了说我只想替换第二个 'a'。

标签: python combinations


【解决方案1】:
from itertools import product

s = "abc{}xig{}{}"

for combo in product(("i", 1), ("e", 3), ("a", 4)):
    print(s.format(*combo))

生产

abcixigea
abcixige4
abcixig3a
abcixig34
abc1xigea
abc1xige4
abc1xig3a
abc1xig34

编辑: 以更一般的方式,你想要这样的东西:

from itertools import product

def find_nth(s, char, n):
    """
    Return the offset of the nth occurrence of char in s,
      or -1 on failure
    """
    assert len(char) == 1
    offs = -1
    for _ in range(n):
        offs = s.find(char, offs + 1)
        if offs == -1:
            break
    return offs

def gen_replacements(base_string, *replacement_values):
    """
    Generate all string combinations from base_string
      by replacing some characters according to replacement_values

    Each replacement_value is a tuple of
      (original_char, occurrence, replacement_char)
    """
    assert len(replacement_values) > 0
    # find location of each character to be replaced
    replacement_offsets = [
        (find_nth(base_string, orig, occ), orig, occ, (orig, repl))
        for orig,occ,repl in replacement_values
    ]
    # put them in ascending order
    replacement_offsets.sort()
    # make sure all replacements are actually possible
    if replacement_offsets[0][0] == -1:
        raise ValueError("'{}' occurs less than {} times".format(replacement_offsets[0][1], replacement_offsets[0][2]))
    # create format string and argument list
    args = []
    for i, (offs, _, _, arg) in enumerate(replacement_offsets):
        # we are replacing one char with two, so we have to
        # increase the offset of each replacement by
        # the number of replacements already made
        base_string = base_string[:offs + i] + "{}" + base_string[offs + i + 1:]
        args.append(arg)
    # ... and we feed that into the original code from above:
    for combo in product(*args):
        yield base_string.format(*combo)

def main():
    s = "abcixigea"

    for result in gen_replacements(s, ("i", 1, "1"), ("e", 1, "3"), ("a", 2, "4")):
        print(result)

if __name__ == "__main__":
    main()

产生与上面完全相同的输出。

【讨论】:

  • 很好,谢谢!但是,如果我尝试使用大于元组长度的 {} 数,则会收到错误“IndexError:元组索引超出范围”。我想要一个适用于所有通用案例的解决方案,而不仅仅是与我的示例相关。
  • 我更好地理解了它的作用以及为什么会出现错误。我不得不在主元组中添加额外的元组来匹配所有的 {} 并且它工作得很好。即使它不是那么优雅,它也能完成工作。欢迎替代解决方案:)
  • “没那么优雅”?在批评之前,请随意制作一个“更优雅”的版本。
  • 哦不,我不是在批评你的方法,它很优雅!我在谈论我添加额外的元组以匹配 {} 的数量,而不是扩展您的解决方案(即,就像您在编辑中所做的那样)。再次感谢!
猜你喜欢
  • 2014-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
  • 2020-08-31
  • 2019-06-15
相关资源
最近更新 更多