怎样才能优雅地替换字符串中的每个元素(字符)?

时间:2017-12-15 18:12:35

标签: python

这是两个字符串:

d = '123'
list1 = '12345'

显然,d中包含三个元素,分别是'1','2','3'。 现在,尝试使用list1中的元素替换这三个元素。并打印出所有可能的组合。

所以,我们可以将'1'替换为'1','2','3','4','5',或者不要忘记我们需要为'2'做同样的事情d中的'3'。

然后结果如下:

'111', '112', '113', '114', '115'
'121', '122', '123', '124', '125'
...
...
...
'541', '542', '543', '544', '545'
'551', '552', '553', '554', '555'

非常感谢@tobais_k提醒,这个问题可以被描述为“输入中的相等字符被映射到输出中的相等字符”。

因此,如果我们有d1 = '111222333'输出将是

'111111111', '111111222', '111111333', '111111444', '111111555',
'111222111', '111222222', ..., 
'555555111', '555555222', '555555333', '555555444', '555555555'

如果d2 = '123123123',情况与d1会有很大不同,因为我们无法从d2获得'111111222'。结果将是:

'111111111', '112112112', '113113113', '114114114', '115115115',
'121121121', '122122122', '123123123', '124124124', '125125125',
...
'551551551', '552552552', '553553553', '554554554', '555555555'

这是我的代码,用于给出上面的结果:

d = '123'
list1 = '12345'
list2 = sorted(set(d))

# make a dict to recognize the position of each element
position = {}
for i in list2:
    position[i] = []
    for (x,y) in enumerate(d):
        if y==i:
            position[i].append(x)
print(position)
# in this case,it should return{'1': [0], '2': [1], '3': [2]}


for i1 in list1:
    for i2 in list1:
        for i3 in list1:
            c = list(d)
            # because we know the exact position for each element
            # then we make a new list every time
            # just replace the right element at the right place
            f = [i1, i2, i3]
            j = 0
            for (k,v) in position.items():
                for x in v:
                    c[x]=f[j]
                j += 1
            print(''.join(y for y in c))

您可能希望尝试使用d = '123123123'd = '111222333'来检查结果,但请注意它们是代码中的几个嵌入式“for”,并使此代码不是Pythonic。

有没有更优雅的方式来给出相同的结果?

我的代码看起来有点尴尬,毫无疑问我可以从你身上学到更多东西;那么,这种技能在其他情况下会有所帮助,例如:我们有一个复杂的encryptedD ='bccle',key ='ap';通过这个简单的程序后,我们可能会发现D实际上意味着'苹果'。

4 个答案:

答案 0 :(得分:6)

试试产品:

<?php


$string = "<?xml version='1.0'?> 
<Item>
<Node>
<CodeID>1533</CodeID>
<Size>36|37|38</Size>
</Node>
<Node>
<CodeID>L534</CodeID>
<Size>S|M|L</Size>
</Node>
</Item>";

$xml = simplexml_load_string($string);
$xml2 = simplexml_load_string($string);
//$xml = simplexml_load_file("./Items.xml", 'SimpleXMLElement', LIBXML_NOCDATA);
$i=0;
foreach ($xml as $item)
{
    $variations_array = explode("|",$item->Size);

    $j=0;
    foreach ($variations_array as $variation)
    {
        $xml2->Node[$i]->Variations->Variation[$j] = $variation;
        $j++;
    }
$i++;   
}
echo $xml2->asXML();
//$xml2->asXML("./Items2.xml");

/*
<?xml version="1.0"?>
<Item>
<Node>
<CodeID>1533</CodeID>
<Size>36|37|38</Size>
<Variations>
<Variation>36</Variation>
<Variation>37</Variation>
<Variation>38</Variation>
</Variations>
</Node>
<Node>
<CodeID>L534</CodeID>
<Size>S|M|L</Size>
<Variations>
<Variation>S</Variation>
<Variation>M</Variation>
<Variation>L</Variation>
</Variations>
</Node>
</Item>
*/

?>

如果您想使用import itertools s = '12345' ["".join(p) for p in itertools.product(s, repeat=3)] ,可以将重复参数更改为d = '123'

问题得到了更新,另一种解决方案是:

len(d)

然而..我跑了一些小时间,接受的答案更快。所以我坚持这一点。

答案 1 :(得分:2)

您可以使用itertools.product获取所有组合,并将这些组合与str.maketransstr.translate结合起来,将原始字符映射到替换项。

>>> d = "121"
>>> list1 = 'abc'
>>> chars = list(set(d))
>>> [d.translate(str.maketrans(dict(zip(chars, prod))))
...  for prod in itertools.product(list1, repeat=len(chars))]
['aaa', 'aba', 'aca', 'bab', 'bbb', 'bcb', 'cac', 'cbc', 'ccc']

让我们看看中间结果,以便更好地了解正在发生的事情:

>>> [prod for prod in itertools.product(list1, repeat=len(chars))]
[('a', 'a'), ('a', 'b'),... , ('c', 'c')]
>>> [dict(zip(chars, prod)) for prod in itertools.product(list1, repeat=len(chars))]
[{'2': 'a', '1': 'a'}, {'2': 'b', '1': 'a'},... , {'2': 'c', '1': 'c'}]
>>> [str.maketrans(dict(zip(chars, prod))) for prod in itertools.product(list1, repeat=len(chars))]
[{49: 'a', 50: 'a'}, {49: 'a', 50: 'b'},... , {49: 'c', 50: 'c'}]

或作为生成器功能(基于@AntonvBR的第一版)

def func(values, order):
    """ Returns the combinations of values defined by the set 
    of the order translated back to the length of the order.

    >>> list(func(values='ab', order='1212'))
    ['aaaa', 'baba', 'abab', 'bbbb']
    """
    s = list(set(order))
    for prod in itertools.product(values, repeat=len(s)):
        d = dict(zip(s, prod))
        yield order.translate(str.maketrans(d))

答案 2 :(得分:0)

  

我们有一个复杂的encryptedD ='bccle',key ='ap';通过这个简单的程序后,我们可能会发现D实际上意味着'苹果'。

import itertools

d = 'bccle'
key = 'ap'

步骤:1 - 创建列表列表:[[b],[c],[c],[l],[e]]

z = [list(x) for x in d]

步骤:2 - 将关键字母附加到列表中:[[b,a,p],[c,a,p],[c,a,p],[l,a,p][e,a,p]]

z = [set(y + list(key)) for y in z]

步骤3 - 使用itertools.product()创建单词组合列表。

[''.join(t) for t in list(itertools.product(*z))]

'apple'是结果之一。

答案 3 :(得分:0)

每个人都会给你一个循环解决方案,如果你想尝试一些不同的方法而不是那个旧的循环方法那么你可以试试这个:

  

在一行中没有循环:

[['111', '112', '113', '114', '115', '121', '122', '123', '124', '125', '131', '132', '133', '134', '135', '141', '142', '143', '144', '145', '151', '152', '153', '154', '155'], ['211', '212', '213', '214', '215', '221', '222', '223', '224', '225', '231', '232', '233', '234', '235', '241', '242', '243', '244', '245', '251', '252', '253', '254', '255'], ['311', '312', '313', '314', '315', '321', '322', '323', '324', '325', '331', '332', '333', '334', '335', '341', '342', '343', '344', '345', '351', '352', '353', '354', '355']]

输出:

{{1}}