Хранение двух связанных значений в Python

Я понимаю, что в Python есть разные способы хранения данных, но я не могу понять, что использовать для моих нужд.

Я сделал небольшую клиент-серверную игру, и я хочу, чтобы количество догадок, которое им потребовалось, было их счетом. Затем я хотел бы записать их имя (в настоящее время IP-адрес) вместе со счетом в файл, чтобы создать список высоких результатов. Хотя я могу сделать это прекрасно, я хочу хранить максимум 5 баллов и иметь возможность сортировать их так, чтобы, когда я отображаю пользователю самые высокие баллы и имена, самый низкий (являющийся лучшим) балл был вверху. Я также хотел бы, чтобы имя пользователя существовало более одного раза.

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

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

Какой был бы самый простой способ сохранить имя и оценку вместе, не используя какую-то экстремальную кривую обучения, такую ​​​​как SQL?


person PairedPrototype    schedule 01.11.2015    source источник


Ответы (2)


Вы можете сохранить список кортежей, каждый из которых содержит данные в определенном порядке (например, счет, имя и т. д.). Затем вы можете отсортировать список, используя функцию list.sort(), определив функцию f для сравнения результатов и передав функцию в sort().

person Vinay    schedule 01.11.2015
comment
Не могли бы вы привести пример того, как эта функция будет работать? - person PairedPrototype; 01.11.2015
comment
Вы можете посмотреть его здесь stackoverflow.com/ вопросы/3216398/ . Это напрямую использует лямбда-функцию. - person Vinay; 01.11.2015
comment
Шикарно, посмотрю. Спасибо! - person PairedPrototype; 01.11.2015
comment
Похоже, это не работает со списками. Есть ли что-нибудь подобное для списков? Поскольку, когда я читаю свой файл, он по умолчанию создает списки в списке, я не думаю, что есть способ прочитать его в кортежи в списке? В настоящее время я использую это для чтения из моего файла: with open('Scores.csv', 'r') as scores: reader = csv.reader(scores) tscores = [[str(e) for e in r] for r in reader] Итак, теперь tscores = [[score1, IP1], [score2, IP2]]. - person PairedPrototype; 01.11.2015
comment
Кортежи были просто идеей. Вы можете напрямую использовать их для списка списков, и приведенная выше ссылка явно позволяет это сделать. - person Vinay; 01.11.2015
comment
Кажется, я нашел проблему. Значения файла считываются как строка, поскольку tscores = [[str(e) for e in r] for r in reader] с использованием int(e) вызывает ошибку из-за IP-адреса. Поэтому я думаю, что мне нужно сделать первое значение целым числом. Но, поскольку у меня это tscores.sort(key=lambda x: x[0]), которое должно сортироваться по первому значению, но оно читает второе, которое является IP-адресом, так как это то, что появляется в ошибке? Почему он читает второе значение вместо первого, как указано? Я дважды проверил, чтобы убедиться, что он также отформатирован [[score, IP]]. - person PairedPrototype; 02.11.2015
comment
Просто чтобы уточнить, ошибка TypeError: unorderable types: int() < str() - person PairedPrototype; 02.11.2015
comment
Вычеркните второй абзац в комментарии перед последним. IP не имеет ничего общего с текущей ошибкой, которая была вызвана моей попыткой исправить текущую ошибку. Так это потому, что мне нужно, чтобы первое значение было int(), а не str(), что означает, что мне придется как-то перебирать каждое из них. - person PairedPrototype; 02.11.2015
comment
Мне удалось изменить их на int(), используя предложения в этой теме stackoverflow.com/questions/9869524/ И этот метод работает отлично! Спасибо за помощь! - person PairedPrototype; 02.11.2015

Формат с довольно небольшой кривой обучения будет json.

По сути, это словарь, каждый ключ может быть числом, строкой, логическим значением, числом с плавающей запятой, массивом или другим словарем (может иметь больше типов).

>>> d = {}
>>> d['someId'] = {'somekey': [0,2,3]}
>>> d
{'someId': {'somekey': [0, 2, 3]}}
>>> d['someId']['somekey']
[0, 2, 3]
>>> d['someId']['number'] = 23456776543
>>> d['someId']['number']
23456776543

Как только вы освоите json, подумайте об ODM/ORM для монго.

Или на данный момент добавьте вспомогательную функцию для сортировки по счету, вытягивая счет и имя.

>>> d = {'user1': {'name': 'howdy', 'score': 11},'user2': {'name': 'howdy2', 'score': 12}}
>>> d.keys()
['user2', 'user1']
>>> for user_id in d.keys():
...     print(d[user_id]['name'], d[user_id]['score'])
... 
('howdy2', 12)
('howdy', 11)

Если необходимо настроить реляционные данные и модели, рассмотрите sqlite, поскольку он имеет основы и не так сложен в настройке, как postgres или mysql.

Пример json чтения:

Пример json написания:

person jmunsch    schedule 01.11.2015
comment
Я мог бы попробовать это, но была бы проблема. Поскольку имя пользователя является IP-адресом, оно может встречаться несколько раз, поэтому, если хотите, оно не может быть первичным ключом. В настоящее время я должен написать IP, score. Но я также столкнулся с другой проблемой: вы не можете записывать списки в файл, я должен сначала преобразовать их в строку, которая, когда вы ее читаете, конечно, по-прежнему остается строкой, и преобразование ее обратно в список будет иметь каждый символ как ценность. Будет ли полезно, если я опубликую свой код? - person PairedPrototype; 01.11.2015
comment
Я подумал, может быть, я мог бы иметь 5 ключей, то есть числа 1-5, и использовать их в качестве ключа, чтобы ключ 1 всегда содержал наивысший балл. Но если бы был достигнут новый наивысший балл, как бы я понизил его значения, чтобы ввести новый максимальный балл в ключ 1 и удалить самый низкий балл, чтобы оставалось только максимум 5 ключей? - person PairedPrototype; 01.11.2015
comment
Вы можете записать список в файл json и вместо использования IP-адреса в качестве ключа использовать уникальный ключ для идентификации пользователя. Mongo использует идентификатор объекта bson. Если вы хотите, чтобы уникальные ключи были числами 1-5, это нормально, вы можете это сделать. Чтобы получить отсортированный список, вам нужно будет написать вспомогательную функцию, которая сохраняет идентификаторы для минимальных и максимальных результатов. Вы можете сделать это с помощью 1 цикла for. - person jmunsch; 01.11.2015
comment
Я добился некоторого прогресса, используя csv. Теперь я могу читать и записывать значения, но у меня возникают проблемы с их сортировкой, потому что это список из двух значений в списке. то есть mylist.sort() не работает, потому что значения внутри mylist имеют тип данных списка, а не str или int, как этот mylist = [[score1, ip1], [score2, ip2]]. По сути, мне нужно отсортировать mylist на основе mylist[n[0]], где n - список внутри mylist, если это имеет смысл? Я не уверен, что это возможно без извлечения каждого значения из mylist и сравнения n[0] каждого извлеченного значения, что является вопросом, совершенно отличным от этого. - person PairedPrototype; 01.11.2015
comment
Я только что понял, что это в основном то, что @Vinay говорит в своем ответе ниже. - person PairedPrototype; 01.11.2015