列表中唯一字符串的最大值

时间:2015-01-27 15:22:19

标签: python list itertools

您好我正在尝试列出列表中唯一字符串的最大值。

示例:

a = ['DS10.json', 'DS11.json', 'DT4.json', 'DT5.json', 'DT6.json', 'CJ6.json', 'CJ7.json']

应该返回以下列表:

['DS11.json', 'DT6.json', 'CJ7.json']

我尝试过以下代码:

def j(l):
    p = []
    for i in l:
        digcode = i.split('.')[0]
        if any(s.startswith(digcode[:2]) for s in p): #there exists prefex in list
            if digcode[2:] > p[[n for n, l in enumerate(p) if l.startswith(digcode[:2])][0]][2:]:
                p.pop([n for n, l in enumerate(p) if l.startswith(digcode[:2])][0])
                p.append(digcode)
            else:
                pass
        else:
            p.append(digcode)
    return p

但是当我将它应用于更大的样本时,它并没有做出准确的工作

>>> o = ['AS6.json', 'AS7.json', 'AS8.json', 'AS9.json', 'BS1.json', 'BS2.json', 'BS3.json', 'BS4.json', 'BS5.json', 'CS1.json', 'CS2.json', 'CS3.json', 'CS4.json', 'CS5.json', 'CS6.json', 'DS10.json', 'DS11.json', 'DS4.json', 'DS5.json', 'DS6.json', 'DS7.json', 'DS8.json', 'DS9.json', 'ES4.json', 'ES5.json', 'ES6.json', 'FS5.json', 'FS6.json', 'FS7.json', 'FS8.json', 'MS4.json', 'MS5.json', 'MS6.json', 'MS7.json', 'MS8.json', 'MS9.json', 'NR1.json', 'NR2.json', 'NR3.json', 'NR4.json', 'NR5.json', 'NR6.json', 'NR7.json', 'NR8.json', 'VR1.json', 'VR2.json', 'VR3.json', 'VR4.json', 'VR5.json', 'VR6.json', 'VR7.json', 'VR8.json', 'XS11.json', 'XS9.json']

>>> j(o)
['AS9', 'BS5', 'CS6', 'DS9', 'ES6', 'FS8', 'MS9', 'NR8', 'VR8', 'XS9']

这是不正确的,因为有一个XS11和DS11作为例子。

如果有人可以帮助我纠正我的问题或者找到一个更简单的问题解决方案,我将不胜感激。谢谢

2 个答案:

答案 0 :(得分:2)

您正在进行字符串比较; '9'大于'11',因为字符'9'后来出现在字母表中。你必须先将它们转换为整数。

我使用词典将前缀映射到最大数字:

def find_latest(lst):
    prefixes = {}
    for entry in lst:
        code, value = entry[:2], int(entry.partition('.')[0][2:])
        if value > prefixes.get(code, (float('-inf'), ''))[0]:
            prefixes[code] = (value, entry)
    return [entry for value, entry in prefixes.values()]

这样效率更高,因为它不会每次循环遍历整个输入列表;你正在处理列表N ^ 2次(添加一个元素,你要添加N个测试来完成);它会在N个步骤中处理您的列表。因此,不是对10个元素进行100次测试,而是执行10次测试。

演示:

>>> sample = ['AS6.json', 'AS7.json', 'AS8.json', 'AS9.json', 'BS1.json', 'BS2.json', 'BS3.json', 'BS4.json', 'BS5.json', 'CS1.json', 'CS2.json', 'CS3.json', 'CS4.json', 'CS5.json', 'CS6.json', 'DS10.json', 'DS11.json', 'DS4.json', 'DS5.json', 'DS6.json', 'DS7.json', 'DS8.json', 'DS9.json', 'ES4.json', 'ES5.json', 'ES6.json', 'FS5.json', 'FS6.json', 'FS7.json', 'FS8.json', 'MS4.json', 'MS5.json', 'MS6.json', 'MS7.json', 'MS8.json', 'MS9.json', 'NR1.json', 'NR2.json', 'NR3.json', 'NR4.json', 'NR5.json', 'NR6.json', 'NR7.json', 'NR8.json', 'VR1.json', 'VR2.json', 'VR3.json', 'VR4.json', 'VR5.json', 'VR6.json', 'VR7.json', 'VR8.json', 'XS11.json', 'XS9.json']
>>> def find_latest(lst):
...     prefixes = {}
...     for entry in lst:
...         code, value = entry[:2], int(entry.partition('.')[0][2:])
...         if value > prefixes.get(code, (float('-inf'), ''))[0]:
...             prefixes[code] = (value, entry)
...     return [entry for value, entry in prefixes.values()]
... 
>>> find_latest(sample)
['FS8.json', 'VR8.json', 'AS9.json', 'MS9.json', 'BS5.json', 'CS6.json', 'XS11.json', 'NR8.json', 'DS11.json', 'ES6.json']

答案 1 :(得分:1)

看起来您的digcode[2:]值正在按字典顺序(字典顺序)进行比较,而不是数字

因此9被认为是“大于”11,因为在单词列表中,以“9”开头的单词将出现在以“11”开头的单词之后。

为了进行比较,您应该将digcode[2:]转换为数字int(digcode[2:])

if digcode[2:] > p[[n for n, l in enumerate(p) if l.startswith(digcode[:2])][0]][2:]:

if int(digcode[2:]) > int(p[[n for n, l in enumerate(p) if l.startswith(digcode[:2])][0]][2:]):

这给出了:

>>> j(o)
['AS9', 'BS5', 'CS6', 'DS11', 'ES6', 'FS8', 'MS9', 'NR8', 'VR8', 'XS11']