【问题标题】:Aggregation json elements by sub-string按子字符串聚合 json 元素
【发布时间】:2019-02-08 13:38:36
【问题描述】:

我有以下结构:

[
    {
        "name": "a-v1",
        "date": "2018-05-08T08:40:35.000Z"
    },
    {
        "name": "a-v2",
        "date": "2018-05-20T08:40:35.000Z"
    },
    {
        "name": "a-v3",
        "date": "2018-05-22T08:40:35.000Z"
    },
    {
        "name": "b-v1",
        "date": "2018-02-08T08:40:35.000Z"
    },
    {
        "name": "b-v2",
        "date": "2018-05-08T08:40:35.000Z"
    },
    {
        "name": "b-v3",
        "date": "2018-05-10T08:40:35.000Z"
    },
    {
        "name": "c-v1",
        "date": "2018-10-08T08:40:35.000Z"
    },
    {
        "name": "c-v2",
        "date": "2018-11-08T08:40:35.000Z"
    },
    {
        "name": "d-v1",
        "date": "2018-08-08T08:40:35.000Z"
    }
]

每个name 都结合了类型和版本(例如a-v1 中,类型中有a,v1 是版本)。

我如何创建所有name 的列表,它们不是最新的 2 个版本? 在我们的例子中,输出将是:

a-v1
b-v1

知道如何在 Python 中做到这一点吗?我一直在考虑计算子字符串。例如:使用- 作为分隔符,并计算我找到字符串左侧的次数(aa,b,c)。这可以在 Python 中实现吗?有更好的想法吗?

【问题讨论】:

  • 我认为您提出的方法没有任何问题。
  • 输出还应该包含 a-v3,d-v1,... ?为什么只有 a-v1 和 b-v1?
  • 或者您可以使用诸如限制大小的优先级队列之类的东西,我认为这可能是矫枉过正。
  • @newbie 我有 3 个版本的 a,我只想保留 2 个最新版本,所以输出将是 a-v1(这是最旧的版本)。与b 相同。至于cd,我没有超过2个版本,所以输出对他们来说是空的。
  • 您是按v1 之类的后缀排序,还是也考虑日期?你需要检查 v-somehting 的顺序是否在正确的日期?

标签: python json string dictionary


【解决方案1】:

假设您的列表 L 是预先排序的,如您的示例所示,您可以使用 itertools.groupby 并使用列表切片:

from itertools import chain, groupby
from operator import itemgetter

grouper = groupby(map(itemgetter('name'), L), key=lambda x: x.split('-')[0])
groups = (list(vals)[:-2] for _, vals in grouper)

res = list(chain.from_iterable(filter(None, groups)))

# ['a-v1', 'b-v1']

【讨论】:

  • 感谢您的回答。我的用例已更改。我应该打开一个新问题还是更新当前问题?新的用例应该会容易得多,但我仍然有一些问题。
  • @Omri,您应该打开一个新问题,因为您在这里已经有了几个答案。如果您已经检查过此解决方案中的任何解决方案,请随时接受一个以便其他用户知道。
【解决方案2】:

使用稍微不同的数据格式会更容易解决问题。

你没有写任何代码,所以我不会给你一个完整的答案:

data = [{'name': 'a-v1', 'date': '2018-05-08T08:40:35.000Z'}, {'name': 'a-v2', 'date': '2018-05-20T08:40:35.000Z'}, {'name': 'a-v3', 'date': '2018-05-22T08:40:35.000Z'}, {'name': 'b-v1', 'date': '2018-02-08T08:40:35.000Z'}, {'name': 'b-v2', 'date': '2018-05-08T08:40:35.000Z'}, {'name': 'b-v3', 'date': '2018-05-10T08:40:35.000Z'}, {'name': 'c-v1', 'date': '2018-10-08T08:40:35.000Z'}, {'name': 'c-v2', 'date': '2018-11-08T08:40:35.000Z'}, {'name': 'd-v1', 'date': '2018-08-08T08:40:35.000Z'}]
temp = [d['name'].split('-') for d in data]
# [['a', 'v1'], ['a', 'v2'], ['a', 'v3'], ['b', 'v1'], ['b', 'v2'], ['b', 'v3'], ['c', 'v1'], ['c', 'v2'], ['d', 'v1']]
versions = [(letter, int(v[1:])) for letter, v in temp]
sorted(versions)

它输出:

[('a', 1),
 ('a', 2),
 ('a', 3),
 ('b', 1),
 ('b', 2),
 ('b', 3),
 ('c', 1),
 ('c', 2),
 ('d', 1)]

您现在可以尝试使用 itertools.groupby 按字母对版本进行分组,并删除每个版本,但每个组的最后两个版本除外。

【讨论】:

    猜你喜欢
    • 2018-08-02
    • 1970-01-01
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多