2012-06-01 2 views
3

Некоторые данные о данных: в игре играют разные игры, и в каждом из них есть несколько игроков. Каждая игра состоит из нескольких раундов, и в каждом раунде каждый вовлеченный игрок делает действие. То, что я пытаюсь сделать здесь, - построить структуру данных в памяти для хранения полной истории отдельных действий, предпринятых игроками во всех играемых играх.Альтернативная структура данных, необходимая для глубоко вложенного положения словаря/карты.

Очевидной структура является глубоко вложенным словарем/HashMap, где каждый game_id отображается рядом с player_id, и каждый player_id отображаются на различные round_number с, и каждым round_number отображается на action.

Иными словами, game_id:player_id:round_number:action. С другой стороны, я также могу использовать game_id:round_number:player_id:action

Проблема возникает при попытке доступа к структурам данных выше для различных аналитических целей. Например, неудобно иметь game_id:player_id:round_number:action, если я хочу знать все действия игроков в определенном раунде данной игры. И наоборот, одинаково неудобно иметь game_id:round_number:player_id:action, если я хочу знать все действия, сделанные определенным игроком в ходе данной игры. К сожалению, в моем случае мне нужно часто задавать оба этих вопроса.

Интересно, существует ли единая структура данных, которая может хранить такие данные и удобна для доступа к данным как на уровне игрока, так и на уровне раунда, как описано выше. Реализация будет в Python, если это имеет значение.

EDIT: несколько человек рекомендовали базу данных sqlite в памяти для обработки таких реляционных запросов. Тем не менее, его работа может быть проблемой для меня, как описано здесь: SQLite Performance Benchmark -- why is :memory: so slow...only 1.5X as fast as disk?

+1

Похоже, вам нужна реляционная база данных, которая живет в памяти. Возможно, попробуйте изучить inMemory SQLite. http://www.sqlite.org/inmemorydb.html – Justin

+0

Вас интересует только просмотр двух примеров, которые вы даете? Или вы хотите делать произвольные запросы? –

+0

@ DougT. Помимо этих двух случаев, я также хочу найти конкретное действие, сделанное любым игроком в любом раунде любой заданной игры. – skyork

ответ

3

Один из способов - хранить данные в dict, но поддерживать индексы, чтобы обеспечить быстрый доступ к различным представлениям в ваших данных. Вы можете структурировать это с помощью класса или просто функций. Вот jist этого (непроверенные):

from collections import defaultdict 

game_dict = {} # keyed by (game, player, round) tuple 
game_player_ix = defaultdict(list) 
game_round_ix = defaultdict(list) 

def add_action(game, player, round): 
    game_dict[(game, round, player)] = action # track the action in the main dict 
    game_player_ix[(game, player)].append(round) # keep an index for lookups by player 
    game_round_ix[(game, round)].append(player) # another index for lookups by round 

def get_all_player_actions(game, player): 
    return (game_dict[(game,player,round)] for round in game_round_ix[(game, player)]) # iterator 

def get_all_round_actions(game, round): 
    return (game_dict[(game,player,round)] for player in game_player_ix[(game, round)]) # iterator 
+0

Одним из хороших моментов в этом ответе также является то, что он использует кортежи в качестве словарных клавиш, что, кажется, является хорошим способом хранения данных, на которые помечены несколько идентификаторов, как в вашем случае. – silvado

1

Я бы рекомендовал либо

  1. Дать класс, который имеет функции, которые окутывают общий шаблон доступа к вашей вложенной карте.
  2. Использование sqlite3 database.

EDIT:

я неправильно вопрос, извините.

Я не могу представить ни одной структуры данных, которая бы это сделала, хотя было бы не так уж плохо воспроизвести данные. Сделайте игрока классом, и вы можете иметь раунды, чтобы хранить карту игроков для действий, а также иметь класс игрока, содержащий список действий, предпринятых этим игроком.

+0

спасибо за предложения. Но как (1) решить проблему здесь? Если это одна и та же базовая структура данных, функции обертки по-прежнему сталкиваются с той же проблемой, что и упомянутая. (2) здесь не является оптимальным, так как я хочу избежать ввода/вывода. – skyork

+0

Я отредактировал свой ответ. Я должен указать, что если имеется конечный список возможных действий, то репликация данных как таковая имеет небольшие накладные расходы, так как игрок будет хранить ссылки только на действия. – cabbagebot

+1

@skyork: вы можете полностью создать базу данных SQLite в оперативной памяти с помощью 'sqlite3.connect (": memory: ")'. –

0

Вы можете хранить множество кортежей, где каждый кортеж магазинов просто (game_id, player_id, round_number, действие). Вы также можете просто использовать имя interned strings имени игрока вместо id.Если вы не знаете, какой анализ вы должны сделать, этот формат оставляет все поля одинаково доступными для статистического анализа и их просто конвертировать в хранилище в базе данных, если вы почувствуете необходимость в будущем.

A named tuple также может быть использован.

Смежные вопросы