我是这个网站的新手,对于我的第一个问题,请求有点具体,但我会尝试概括我的问题。
我的数据库位于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
答案 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}