【问题标题】:Replacing chars in a string in every way以各种方式替换字符串中的字符
【发布时间】:2012-11-07 17:29:06
【问题描述】:

我正在寻求一个函数的帮助,该函数接受一个字符串,并以各种方式替换该字符串中的每个字符。我不太确定如何表达我的问题以使其有意义,因此我将向您展示它应该做什么。

stars('1')
returns ['*']

stars('12')
returns ['*1', '1*', '**']

stars('123')
returns ['*23', '1*3', '12*', '**3', '*2*', '**1', '***']

stars('1234')
returns ['*234', '1*34', '12*4', '123*', '**34', '*2*4', '*23*', '1**4', '1*3*', 
         '12**', '***4', '**3*', '*2**', '1***', '****']

这一切都是手工完成的,但即使我犯了一个错误,你也应该知道我现在在寻找什么。最后一种情况(所有 *)不是必需的,但我把它放在那里以确保问题得到理解。

这是我到目前为止想出的,但它并不完全奏效。

def stars(n):
    lst = []
    length = len(n)
    for j in xrange(0, length):
        p = list(n)
        for k in xrange(j, length):
            p[k] = '*'
            lst += [''.join(p)]
    return lst

输出:

'1' returns ['*']
'12' returns ['*2', '**', '1*']
'123' returns ['*23', '**3', '***', '1*3', '1**', '12*']
'1234' returns ['*234', '**34', '***4', '****', '1*34', '1**4', '1***', '12*4', '12**', '123*']

任何帮助将不胜感激。如果可能的话,希望用 Python 回答这个问题,但如果您不了解 Python,那么伪代码或其他语言也是可以接受的。如果写的清楚,我相信我可以自己把它转换成 Python。

【问题讨论】:

  • 这里的理论和伪代码:stackoverflow.com/questions/361/…
  • 这与排列无关——如果有的话,他需要遍历所有字符子序列
  • 我猜你的第二个例子应该返回['x2', '1x', 'xx'],你的第三个应该返回['x23', '1x3', '12x', 'xx3', 'x2x', '1xx', 'xxx']

标签: python


【解决方案1】:

我认为 Python 中的规范方法是使用 itertools 模块:

>>> from itertools import product, cycle
>>> s = 'abcde'
>>> [''.join(chars) for chars in product(*zip(s, cycle('*')))]
['abcde', 'abcd*', 'abc*e', 'abc**', 'ab*de', 'ab*d*', 'ab**e', 'ab***', 
 'a*cde', 'a*cd*', 'a*c*e', 'a*c**', 'a**de', 'a**d*', 'a***e', 'a****', 
 '*bcde', '*bcd*', '*bc*e', '*bc**', '*b*de', '*b*d*', '*b**e', '*b***',
 '**cde', '**cd*', '**c*e', '**c**', '***de', '***d*', '****e', '*****']

然后你可以只扔第一个不带任何星星,但这似乎有点神奇。

ISTM 如果您不想使用内置的笛卡尔积函数,您还有另外两种方法:您可以使用递归,或者您可以利用您想要打开和关闭每颗星的事实,a二进制开关。这意味着使用n 字母,您将有 2^n(-1,如果您删除无星号的情况)返回的可能性,并且是否在某处放置星号对应于相应位是否在数字已设置(例如,对于“abc”,您将从 1 循环到 7(含),1 = 001 表示您将一颗星放在最后一个位置,7 = 111 表示您将一颗星放在任何地方,等等)

最后一个很容易实现,所以我把它留给你。 :^)

【讨论】:

  • 这正是我所希望的答案。非常感谢你。我将分解列表理解,以便更好地理解它在做什么。我也很喜欢你的二进制开关想法。再次感谢。
  • 很高兴为您提供帮助。 productzipcycle 很方便(zip 最重要的是,每个人都使用它。)如果这是一个类,使用二进制或递归方法可能是个好主意,不过。
  • +1。我实现了二进制方法,然后看到了你的答案。
  • 不是为了上课,只是为了好玩。这是我刚刚在您的帮助下解决的 Project Euler 问题 51。可能是一种疯狂的解决方法,但它确实有效。
  • +1 - 没有什么建设性的补充,只是那些让我想在 Python 上变得更好的很棒的答案之一 :)
【解决方案2】:

您可以将此视为查找和迭代原始字符串中所有字符子序列的问题。 (对于每个子序列,将其中的字符替换为 '*',其余的不要管)。

对于给定的子序列,每个字符要么在其中,要么不在,所以对于一个 N 字符的字符串,有 2^N 个子序列。可能最简单的迭代它们的方法是迭代从 0 到 (2^N)-1 的整数,并使用它们的二进制表示作为字符是否应该被替换的指示

对于 N=3,它看起来像这样:

0  000 abc
1  001 ab*
2  010 a*c
3  011 a**
4  100 *bc
5  101 *b*
6  110 **c
7  111 ***

在 Python 中,你可以这样做:

def stars(input):
    l = len(input)
    for i in xrange(2**l):
        yield ''.join([('*' if i&(2**(l-pos-1)) else ch) for pos, ch in enumerate(input)])

试试看:

>>> print list(stars('abc'))
['abc', 'ab*', 'a*c', 'a**', '*bc', '*b*', '**c', '***']

【讨论】:

    【解决方案3】:

    这是使用combinations 的一种方式:

    from itertools import combinations
    def stars(str):
        N,L = len(str), []
        for k in range(0,N+1):
            for com in combinations(range(N),k):
                S = list(str)
                for x in com: S[x] = '*'
                L.append(''.join(S))
        return L
    

    试试看:

    >>> stars('abc')
    ['abc', '*bc', 'a*c', 'ab*', '**c', '*b*', 'a**', '***']
    >>> stars('1234')
    ['1234', '*234', '1*34', '12*4', '123*', '**34', '*2*4', '*23*', '1**4', '1*3*', '12**', '***4', '**3*', '*2**', '1***', '****']
    

    【讨论】:

      【解决方案4】:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-13
        • 1970-01-01
        • 2012-04-01
        • 1970-01-01
        • 2011-03-20
        • 2012-04-26
        • 2012-09-25
        相关资源
        最近更新 更多