【问题标题】:in-place modification of strings within a list?就地修改列表中的字符串?
【发布时间】:2012-11-11 05:06:04
【问题描述】:

我正在尝试根据以前的属性更改列表的某些元素。因为我需要分配一个中间变量,所以我认为这不能作为列表理解来完成。以下带有注释的代码是我想要实现的:

for H in header:
    if "lower" in H.lower():
        pref="lower"
    elif "higher" in H.lower():
        pref="higher"
    if header.count(H) > 1:
        # change H inplace
        H = pref+H

我想出的最佳解决方案是:

for ii,H in enumerate(header):
    if "lower" in H.lower():
        pref="lower"
    elif "higher" in H.lower():
        pref="higher"
    if header.count(H) > 1:
        header[ii] = pref+H

它不太好用,而且因为索引,我觉得它不像 Python。有没有更好的方法来做到这一点?

具体例子:

header = ['LowerLevel','Term','J','UpperLevel','Term','J']

想要的输出:

header = ['LowerLevel','LowerTerm','LowerJ','UpperLevel','UpperTerm','UpperJ']

请注意,我的解决方案都不起作用:前者根本不会修改header,后者只会返回
header = ['LowerLevel','LowerTerm','LowerJ','UpperLevel','Term','J']
因为修改后count是错误的。

【问题讨论】:

  • 第一个版本有什么问题?
  • 不起作用。 header 的元素永远不会改变; H 每次都会被覆盖。实际上,第二种方式也行不通。
  • 第二个版本通常是就地修改列表的最佳方式。这是enumerate 的主要用途之一。这是完美的pythonic。
  • 字符串是不可变的,因此您根本无法就地更改它们。您总是需要将元素重新分配给列表或创建一个新列表。

标签: python list loops


【解决方案1】:
header   = ['LowerLevel','Term','J','UpperLevel','Term','J']
prefixes = ['lower', 'upper']

def prefixed(header):
    prefix = ''

    for h in header:
        for p in prefixes:
            if h.lower().startswith(p):
                prefix, h = h[:len(p)], h[len(p):]
        yield prefix + h

print list(prefixed(header))

我真的不知道这比你拥有的更好。这是不同...

$ ./lower.py
['LowerLevel', 'LowerTerm', 'LowerJ', 'UpperLevel', 'UpperTerm', 'UpperJ']

【讨论】:

  • +1 表示尝试;我喜欢这种方法。但是,它不适用于我刚刚添加的具体示例(之所以这样做,是因为我看到了您短暂的先前版本)。这个问题 - 我没有说得很清楚 - 是它只考虑了 1 个先前的元素,但我需要回顾一下这个案例的 2 个。
  • @keflavich 我明白了,感谢您更新样本数据。回到绘图板!
【解决方案2】:

类似这样的东西,使用生成器函数:

In [62]: def func(lis):
    pref=""
    for x in lis:
        if "lower" in x.lower():
            pref="Lower"
        elif "upper" in x.lower():    
            pref="Upper"
        if header.count(x)>1:    
            yield pref+x
        else:      
            yield x
   ....:             

In [63]: list(func(header))
Out[63]: ['LowerLevel', 'LowerTerm', 'LowerJ', 'UpperLevel', 'UpperTerm', 'UpperJ']

【讨论】:

    【解决方案3】:

    这应该适用于您提供的数据。

    from collections import defaultdict
    
    def find_dups(seq):
        '''Finds duplicates in a sequence and returns a dict
                of value:occurences'''
        seen = defaultdict(int)
        for curr in seq:
            seen[curr] += 1
        d = dict([(i, seen[i]) for i in seen if seen[i] > 1])
        return d
    
    if __name__ == '__main__':
        header = ['LowerLevel','Term','J','UpperLevel','Term','J']
        d = find_dups(header)
        for i, s in enumerate(header):
            if s in d:
                if d[s] % 2:
                    pref = 'Upper'
                else:
                    pref = 'Lower'
                header[i] = pref + s
                d[s] -= 1       
    

    但它让我毛骨悚然地提出任何建议,对你将使用的整个数据集一无所知。

    祝你好运,

    迈克

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-10
      • 2021-02-11
      • 1970-01-01
      • 2015-01-27
      相关资源
      最近更新 更多