如果一个值相同且其他值较低,则从列表中删除dict

时间:2017-11-24 09:06:20

标签: python

我有一个包含版本号

的dicts的列表
my_list = [{'version': 'v1.2.3', 'major': '1.2'},
           {'version': 'v1.2.7', 'major': '1.2'},
           {'version': 'v1.3.7', 'major': '1.3'},
           {'version': 'v1.4.1a1', 'major': '1.4'},
           {'version': 'v1.3.8b1', 'major': '1.3'},
           {'version': 'v1.3.2', 'major': '1.3'}]

最后,我希望此列表仅包含每个主要版本的最新版本,并删除所有alpha / beta版本。

my_list = [{'version': 'v1.2.7', 'major': '1.2'},
           {'version': 'v1.3.7', 'major': '1.3'}]

我的第一个想法是创建一个新列表并遍历我的列表,如果一个专业不在新列表中,它将被添加,如果它在新列表中,它将进行比较和替换。但我认为可能有更多的pythonic方式。

编辑:还有我想要从列表中删除的alpha和beta版本。

2 个答案:

答案 0 :(得分:4)

itertools.groupby来到resque的另一种情况:

from itertools import groupby

my_list = [{'version': 'v1.2.3', 'major': '1.2'},
           {'version': 'v1.2.7', 'major': '1.2'},
           {'version': 'v1.3.7', 'major': '1.3'},
           {'version': 'v1.4.1a1', 'major': '1.4'},
           {'version': 'v1.3.8b1', 'major': '1.3'},
           {'version': 'v1.3.2', 'major': '1.3'}]

my_list_ = list(filter(lambda x: all(beta not in x['version'] for beta in ('a', 'b')), my_list))  # removing beta-versions

version_f = lambda y: [0 if any(beta in x for beta in ('a', 'b')) else int(x) for x in y['version'].replace('v', '').split('.')]
grouper = lambda x: x['major']

d = [max(k, key=version_f) for _, k in groupby(sorted(my_list, key=grouper), key=grouper)]
print(d)  # -> [{'version': 'v1.2.7', 'major': '1.2'}, {'version': 'v1.3.7', 'major': '1.3'}, {'version': 'v1.4.1a1', 'major': '1.4'}]

注意:

  • 请勿使用名称list。你正在覆盖Python内置的。
  • 如果list-comprehension对您来说太大了,请使用旧的 for循环将其分解。那里没有犯罪。
  • 正如@Coldspeed所提到的,比较版本并不是那么简单,所以为了展示这一点,我冒昧地修改你的输入(添加{'version': 'v1.3.12', 'major': '1.3'})并使lambda更加聪明 1

1。这基于整数lists的Python内置排序方案([1, 3, 10] > [1, 3, 7]返回True)。

答案 1 :(得分:2)

你的想法

你的想法实际上是一个好主意。它很有效,可以用相对Pythonic的方式实现:

import re
releases = [{'version': 'v1.2.3', 'major': '1.2'},
            {'version': 'v1.2.7', 'major': '1.2'},
            {'version': 'v1.3.7', 'major': '1.3'},
            {'version': 'v1.4.1a1', 'major': '1.4'},
            {'version': 'v1.3.8b1', 'major': '1.3'},
            {'version': 'v1.3.2', 'major': '1.3'}]

stable_releases = [r for r in releases if 'a' not in r['version']
                                      and 'b' not in r['version']]

latest = {}

def major_minor_build(version):
    return [int(d) for d in re.findall('\d+', version)]

for release in stable_releases:
    version, major = release['version'], release['major']
    latest[major] = max([version, latest.get(major, '')],
                                  key=major_minor_build)

print(latest)
# {'1.2': 'v1.2.7', '1.3': 'v1.3.7'}

输出数据是(major, latest)对的字典,可能比一系列字母更容易使用。

SetuptoolsVersion

版本可能很棘手。我们可以使用pkg_resources.SetuptoolsVersion而不是重新发明轮子。比较已经实施,因此maxsort不需要任何密钥。作为奖励,is_prerelease如果版本是alpha或beta版,则为True:

from pkg_resources import SetuptoolsVersion, parse_version
from itertools import groupby

def get_major(release):
    return release._version.release[:2]

mylist = [{'version': 'v1.2.3', 'major': '1.2'},
         {'version': 'v1.2.7', 'major': '1.2'},
         {'version': 'v1.3.7', 'major': '1.3'},
         {'version': 'v1.4.1a1', 'major': '1.4'},
         {'version': 'v1.3.8b1', 'major': '1.3'},
         {'version': 'v1.3.2', 'major': '1.3'}]

releases = [parse_version(r['version']) for r in mylist]
stable_releases = [r for r in releases if not r.is_prerelease]
stable_releases.sort()

print({major:max(group) for major, group in groupby(stable_releases, key=get_major)})
# {(1, 2): <Version('1.2.7')>, (1, 3): <Version('1.3.7')>}