按列而不是按行替换列表中的字符

时间:2018-04-06 21:25:05

标签: python python-3.x

目前我有以下列表:

counter = [13]
instruments = ['3\t     ---', '2\t    /   \\', '1\t   /     \\', '0\t---       \\       ---', '-1\t           \\     /', '-2\t            \\   /', '-3\t             ---']
score = ['|*************|']

我要做的是用乐谱列表中的字符替换乐器列表中的字符(|除外)。

我目前遇到以下问题

逐行替换字符,而不是逐列替换。

仪器清单:

3        ---
2       /   \
1      /     \
0   ---       \       ---
-1             \     /
-2              \   /
-3               ---

得分列表:

|*************|

预期输出:

3        ***
2       *   *
1      *     *
0   ***       *       
-1             *     
-2              *   
-3               

当前输出:

3        ***
2       *   *
1      *     *
0   ***       *       **
-1                  
-2                 
-3               

这就是我目前正在替换instruments列表中的字符的方式:

for elements in counter:
    current_counter = elements
    count = 0
    for elements in instrument_wave:
        amplitude, form = elements.split('\t')
        for characters in form:
            if characters in ['-', '/', '\\']:
                form = form.replace(characters, '*', 1)
                count += 1
            if count == current_counter:
                break
        for characters in form:
            if characters in ['-', '/', '\\']:
                form = form.replace(characters, '')
        if '-' not in amplitude:
            amplitude = ' ' + amplitude
        new_wave = amplitude + "\t" + form
        waveform.append(new_wave)

任何帮助都会受到赞赏,特别是关于如何修复我的替换字符以使其逐列而不是逐行。

2 个答案:

答案 0 :(得分:3)

要解决您的第一个问题,您需要通过列进行迭代。

如果你压缩列表(通过itertools.zip_longest(),因为它们的长度不一样),你可以按顺序浏览它们并截断结果:

import itertools

cols = list(itertools.zip_longest(*lst, fillvalue=" "))
for i in range(3, 17):  # skip negative signs
    cols[i] = "".join(cols[i]).replace('-', '*', 1)
    cols[i] = "".join(cols[i]).replace('/', '*', 1)
    cols[i] = "".join(cols[i]).replace('\\', '*', 1)
fixed = map("".join, zip(*cols[:17]))  # no need to zip longest

for l in fixed:
    print(l)

查看repl.it上的工作示例,其中输出:

3        ***     
2       *   *    
1      *     *   
0   ***       *  
-1             * 
-2              *
-3   

请注意,它会使用空格填充列表,因此如果不是打印,您可能需要.strip()结果。根据您的分数输入,我会留给您。

另一种选择,可能更清楚:

def convert_and_truncate(lst, cutoff):
    result = []
    for str in lst:
        str = str[0] + str[1:].replace('-', '*')  # skip the negative signs
        str = str.replace('/', '*')
        str = str.replace('\\', '*')
        result.append(str[:cutoff])  # truncate
    return result

因为我们正在截断列表的其余部分,所以替换正在改变它们并不重要。

答案 1 :(得分:0)

没有itertools,而是自填充到列表中最长的部分:

counter = [16]
instruments = ['3\t     ---', '2\t    /   \\', '1\t   /     \\', '0\t---       \\       ---', '-1\t           \\     /', '-2\t            \\   /', '-3\t             ---']
score = ['|*************|']


# get longes part list
maxL = max ( len(p) for p in instruments)

#enlarge all to max length
instrum2 = [k + ' '* (maxL-len(k)) for k in instruments]

# mask out leading - to ~ (we reverse it later)
instrum3 = [k if k[0] != '-' else '~'+''.join(k[1:]) for k in instrum2]

# transpose and join to one lengthy sentence, #### are where we later split again
trans = '####'.join(map(''.join,zip(*instrum3)))


# replace the right amount of /-\ with * after that, replace with space instead   
cnt = 0
maxCnt = score[0].count('*')
result = []
for t in trans:
    if t in '/-\\':
        if cnt < maxCnt:
            result.append('*')
            cnt+=1
        else:
            result.append(' ')
    else:
        result.append(t)

# resultlist back to string and split into columns again
result2 = ''.join(result)
trans2 = result2.split('####')

# transpose back to rows and make - correct
trans3 = [''.join(k).replace('~','-') for k in zip(*trans2 )] 

for p in trans3:
    print(p)

输出:

3        ***             
2       *   *            
1      *     *           
0   ***       *          
-1             *        
-2              *       
-3