如何先按ID然后按发布日期

时间:2018-05-06 21:30:57

标签: python json

我是这个网站的新手,对于我的第一个问题,请求有点具体,但我会尝试概括我的问题。

我的数据库位于MongoDB中,包含视频游戏版本,因此具有相同ID的游戏可以在我的/ releases / endpoint中重复多次,但使用不同的平台。例如;

"data" : [ {
    "date" : 1524528000000,
    "game" : 253,
    "id" : 1,
    "platform" : 2,
  }, {
    "date" : 1524528000000,
    "game" : 253,
    "id" : 2,
    "platform" : 6
  }, {
    "date" : 1943308800000,
    "game" : 253,
    "id" : 3,
    "platform" : 4,
  }]

请注意,存在的三个JSON对象都是关于同一个游戏 [game = 253] ,但每个都有不同的平台。另请注意,第三个对象的发布日期与前两个不同。

我想要完成的是首先按照游戏ID然后按发布日期对我的JSON数据进行分组,以便以某种方式“统一”我的数据。所以在这种情况下,它不是拥有三个JSON对象,而是两个对象,如下所示:

"data" : [ {
    "date" : 1524528000000,
    "game" : 253,
    "id" : 1,
    "platform" : [2, 6],
  },{
    "date" : 1943308800000,
    "game" : 253,
    "id" : 0,
    "platform" : [4],
  }]

第二个对象(最初是第一个JSON中的第三个)没有与第一个对象分组,因为它的发布日期与前两个初始JSON对象不同。

我想在第二个JSON中完成此输出。我所做的是无论发布日期如何,我都将所有JSON对象与相同的游戏ID分组为一个对象(请参阅下面的代码)。我希望将具有相同游戏ID的对象组合在一起,但是如果同一游戏在另一个平台上具有不同的发布日期;我希望它作为一个对象独立存在。

我的代码:

# Important: to sort before grouping
region_list.sort(key=lambda k: k['game'])
# Then use group by with the same key
group = groupby(region_list, lambda k: k['game'])
for game_id, group in group:
    print('id', game_id)
    platforms = []
    date = release_object['date']
    initial_release_object = None
    for release_object in group:
        if initial_release_object is None:
            initial_release_object = release_object
        platforms.append(release_object['platform'])
        print(release_object['date'])
    initial_release_object['platforms'] = platforms

3 个答案:

答案 0 :(得分:0)

如果您跟踪处理过程中已经看过的密钥,您可以累积平台,如:

代码:

def consolidate_platform(data_to_process):
    already_seen = {}
    return_data = []
    for datum in data_to_process:
        key = datum['date'], datum['game']
        if key in already_seen:
            already_seen[key]['platform'].append(datum['platform'])
        else:
            return_data.append(datum)
            already_seen[key] = datum
            datum['platform'] = [datum['platform']]
    return return_data

测试代码:

data = [{
    "date": 1524528000000,
    "game": 253,
    "id": 1,
    "platform": 2,
}, {
    "date": 1524528000000,
    "game": 253,
    "id": 2,
    "platform": 6
}, {
    "date": 1943308800000,
    "game": 253,
    "id": 3,
    "platform": 4,
}]

print(consolidate_platform(data))

结果:

[{'date': 1524528000000L, 'platform': [2, 6], 'game': 253, 'id': 1}, 
 {'date': 1943308800000L, 'platform': [4], 'game': 253, 'id': 3}]

答案 1 :(得分:0)

您可以使用itertools.groupby

import itertools
data = {'data': [{'date': 1524528000000, 'game': 253, 'id': 1, 'platform': 2}, {'date': 1524528000000, 'game': 253, 'id': 2, 'platform': 6}, {'date': 1943308800000, 'game': 253, 'id': 3, 'platform': 4}]}
def clean_data(f):
  def wrapper(d):
    return {'data':list(f(d['data']))}
  return wrapper

@clean_data
def group_data(d):
  for i, [a, b] in enumerate(itertools.groupby(sorted(d, key=lambda x:x['date']), key=lambda x:x['date'])):
     yield (lambda x:{'date':a, 'game':x[0]['game'], 'id':i, 'platform{}'.format(['', 's'][len(x) > 1]):[c['platform'] for c in x]})(list(b))

print(group_data(data))

输出:

{'data': [{'date': 1524528000000, 'game': 253, 'id': 0, 'platforms': [2, 6]}, {'date': 1943308800000, 'game': 253, 'id': 1, 'platform': [4]}]}

答案 2 :(得分:0)

使用itertools.groupby很容易。首先,定义一个键来对dicts进行分组:

def group_key(d):
    return d["date"], d["game"]

然后使用enumerate迭代群组(这将为每个游戏/日期提供唯一ID)。

def cleaner(data):
    data = sorted(data, key=sort_key)
    for i, (_, vs) in enumerate(itertools.groupby(data, group_key)):
        # there is always at least one element
        first = next(vs)
        # The first element of the group contains the date, the game, and the first platform. Add the id.
        d = {"date":first["date"], "game":first["game"], "platform":[first["platform"]], "id":i}
        # add the remaining platform
        d["platform"] += [v["platform"] for v in vs]
        yield d

不要忘记预先对数据进行排序。你也可以更加简洁地构建dict

        first = next(vs)
        yield {"date":first["date"], 
               "game":first["game"], 
               "platform":[first["platform"]]+[v["platform"] for v in vs], 
               "id":i}