Что лучший способ состоит в том, чтобы реализовать вложенные словари?

Похоже, у вас есть проблемы с разрешением публичных центров сертификации. Вы должны попытаться установить / переустановить пакет ca-certificates на целевом хосте, например используя apt:

sudo apt install --reinstall ca-certificates

После этого перезапустите демон docker:

sudo service docker restart

195
задан martineau 30 November 2016 в 15:32
поделиться

12 ответов

class JobDb(object):
    def __init__(self):
        self.data = []
        self.all = set()
        self.free = []
        self.index1 = {}
        self.index2 = {}
        self.index3 = {}

    def _indices(self,(key1,key2,key3)):
        indices = self.all.copy()
        wild = False
        for index,key in ((self.index1,key1),(self.index2,key2),
                                             (self.index3,key3)):
            if key is not None:
                indices &= index.setdefault(key,set())
            else:
                wild = True
        return indices, wild

    def __getitem__(self,key):
        indices, wild = self._indices(key)
        if wild:
            return dict(self.data[i] for i in indices)
        else:
            values = [self.data[i][-1] for i in indices]
            if values:
                return values[0]

    def __setitem__(self,key,value):
        indices, wild = self._indices(key)
        if indices:
            for i in indices:
                self.data[i] = key,value
        elif wild:
            raise KeyError(k)
        else:
            if self.free:
                index = self.free.pop(0)
                self.data[index] = key,value
            else:
                index = len(self.data)
                self.data.append((key,value))
                self.all.add(index)
            self.index1.setdefault(key[0],set()).add(index)
            self.index2.setdefault(key[1],set()).add(index)
            self.index3.setdefault(key[2],set()).add(index)

    def __delitem__(self,key):
        indices,wild = self._indices(key)
        if not indices:
            raise KeyError
        self.index1[key[0]] -= indices
        self.index2[key[1]] -= indices
        self.index3[key[2]] -= indices
        self.all -= indices
        for i in indices:
            self.data[i] = None
        self.free.extend(indices)

    def __len__(self):
        return len(self.all)

    def __iter__(self):
        for key,value in self.data:
            yield key

Пример:

>>> db = JobDb()
>>> db['new jersey', 'mercer county', 'plumbers'] = 3
>>> db['new jersey', 'mercer county', 'programmers'] = 81
>>> db['new jersey', 'middlesex county', 'programmers'] = 81
>>> db['new jersey', 'middlesex county', 'salesmen'] = 62
>>> db['new york', 'queens county', 'plumbers'] = 9
>>> db['new york', 'queens county', 'salesmen'] = 36

>>> db['new york', None, None]
{('new york', 'queens county', 'plumbers'): 9,
 ('new york', 'queens county', 'salesmen'): 36}

>>> db[None, None, 'plumbers']
{('new jersey', 'mercer county', 'plumbers'): 3,
 ('new york', 'queens county', 'plumbers'): 9}

>>> db['new jersey', 'mercer county', None]
{('new jersey', 'mercer county', 'plumbers'): 3,
 ('new jersey', 'mercer county', 'programmers'): 81}

>>> db['new jersey', 'middlesex county', 'programmers']
81

>>>

Редактирование: Теперь словари возврата при запросах с подстановочными знаками (None), и единственные значения иначе.

1
ответ дан Markus Jarderot 23 November 2019 в 05:21
поделиться

Если Ваш набор данных не собирается остаться довольно небольшим, Вы могли бы хотеть рассмотреть использование реляционной базы данных. Это сделает точно, что Вы хотите: помогите добавить количества, выбрав подмножества количеств и даже совокупных количеств по состоянию, графству, размещению или любой комбинации их.

1
ответ дан allyourcode 23 November 2019 в 05:21
поделиться

Мне нравится идея обернуть это в класс и реализовать __getitem__ и __setitem__ таким образом, что они реализовали язык простого запроса:

>>> d['new jersey/mercer county/plumbers'] = 3
>>> d['new jersey/mercer county/programmers'] = 81
>>> d['new jersey/mercer county/programmers']
81
>>> d['new jersey/mercer country']
<view which implicitly adds 'new jersey/mercer county' to queries/mutations>

, Если Вы хотели стать необычными, Вы могли бы также реализовать что-то как:

>>> d['*/*/programmers']
<view which would contain 'programmers' entries>

, но главным образом я думаю, что такой вещью была бы действительно забава реализовать: D

2
ответ дан the Tin Man 23 November 2019 в 05:21
поделиться

Что касается "неприятных блоков попытки/выгоды":

d = {}
d.setdefault('key',{}).setdefault('inner key',{})['inner inner key'] = 'value'
print d

урожаи

{'key': {'inner key': {'inner inner key': 'value'}}}

можно использовать это для преобразования от плоского формата словаря до структурированного формата:

fd = {('new jersey', 'mercer county', 'plumbers'): 3,
 ('new jersey', 'mercer county', 'programmers'): 81,
 ('new jersey', 'middlesex county', 'programmers'): 81,
 ('new jersey', 'middlesex county', 'salesmen'): 62,
 ('new york', 'queens county', 'plumbers'): 9,
 ('new york', 'queens county', 'salesmen'): 36}

for (k1,k2,k3), v in fd.iteritems():
    d.setdefault(k1, {}).setdefault(k2, {})[k3] = v
4
ответ дан vartec 23 November 2019 в 05:21
поделиться

Для легкой итерации по Вашему вложенному словарю, почему не только пишут простой генератор?

def each_job(my_dict):
    for state, a in my_dict.items():
        for county, b in a.items():
            for job, value in b.items():
                yield {
                    'state'  : state,
                    'county' : county,
                    'job'    : job,
                    'value'  : value
                }

Таким образом, если у Вас есть свой compilicated, вложил словарь, выполняющий итерации по нему становится простым:

for r in each_job(my_dict):
    print "There are %d %s in %s, %s" % (r['value'], r['job'], r['county'], r['state'])

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

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

if not my_dict.has_key('new jersey'):
    return False

nj_dict = my_dict['new jersey']
...

Или, возможно, несколько подробный метод, должен использовать получить метод:

value = my_dict.get('new jersey', {}).get('middlesex county', {}).get('salesmen', 0)

, Но для несколько большего количества сжатого пути, Вы могли бы хотеть посмотреть на использование collections.defaultdict, который является частью стандартной библиотеки начиная с python 2.5.

import collections

def state_struct(): return collections.defaultdict(county_struct)
def county_struct(): return collections.defaultdict(job_struct)
def job_struct(): return 0

my_dict = collections.defaultdict(state_struct)

print my_dict['new jersey']['middlesex county']['salesmen']

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

3
ответ дан SpoonMeiser 23 November 2019 в 05:21
поделиться

Как другие предположили, реляционная база данных могла быть более полезна для Вас. Можно использовать sqlite3 базу данных в оперативной памяти в качестве структуры данных, чтобы составить таблицы и затем запросить их.

import sqlite3

c = sqlite3.Connection(':memory:')
c.execute('CREATE TABLE jobs (state, county, title, count)')

c.executemany('insert into jobs values (?, ?, ?, ?)', [
    ('New Jersey', 'Mercer County',    'Programmers', 81),
    ('New Jersey', 'Mercer County',    'Plumbers',     3),
    ('New Jersey', 'Middlesex County', 'Programmers', 81),
    ('New Jersey', 'Middlesex County', 'Salesmen',    62),
    ('New York',   'Queens County',    'Salesmen',    36),
    ('New York',   'Queens County',    'Plumbers',     9),
])

# some example queries
print list(c.execute('SELECT * FROM jobs WHERE county = "Queens County"'))
print list(c.execute('SELECT SUM(count) FROM jobs WHERE title = "Programmers"'))

Это - просто простой пример. Вы могли определить отдельные таблицы для состояний, округов и должностей.

6
ответ дан Roberto Bonvallet 23 November 2019 в 05:21
поделиться

Я нахожу setdefault довольно полезный; Это проверяет, присутствует ли ключ и добавляет его если нет:

d = {}
d.setdefault('new jersey', {}).setdefault('mercer county', {})['plumbers'] = 3

setdefault всегда возвраты соответствующий ключ, таким образом, Вы на самом деле обновляете значения' d' на месте.

Когда дело доходит до итерации, я уверен, что Вы могли записать генератор достаточно легко, если Вы уже не существуете в Python:

def iterateStates(d):
    # Let's count up the total number of "plumbers" / "dentists" / etc.
    # across all counties and states
    job_totals = {}

    # I guess this is the annoying nested stuff you were talking about?
    for (state, counties) in d.iteritems():
        for (county, jobs) in counties.iteritems():
            for (job, num) in jobs.iteritems():
                # If job isn't already in job_totals, default it to zero
                job_totals[job] = job_totals.get(job, 0) + num

    # Now return an iterator of (job, number) tuples
    return job_totals.iteritems()

# Display all jobs
for (job, num) in iterateStates(d):
    print "There are %d %s in total" % (job, num)
7
ответ дан the Tin Man 23 November 2019 в 05:21
поделиться

Если количество уровней вложенности является небольшим, я использую collections.defaultdict для этого:

from collections import defaultdict

def nested_dict_factory(): 
  return defaultdict(int)
def nested_dict_factory2(): 
  return defaultdict(nested_dict_factory)
db = defaultdict(nested_dict_factory2)

db['new jersey']['mercer county']['plumbers'] = 3
db['new jersey']['mercer county']['programmers'] = 81

Используя defaultdict как это избегает большого количества грязных setdefault(), get(), и т.д.

14
ответ дан the Tin Man 23 November 2019 в 05:21
поделиться

Так как у Вас есть дизайн схемы "звезда", Вы могли бы хотеть структурировать его больше как реляционная таблица и меньше как словарь.

import collections

class Jobs( object ):
    def __init__( self, state, county, title, count ):
        self.state= state
        self.count= county
        self.title= title
        self.count= count

facts = [
    Jobs( 'new jersey', 'mercer county', 'plumbers', 3 ),
    ...

def groupBy( facts, name ):
    total= collections.defaultdict( int )
    for f in facts:
        key= getattr( f, name )
        total[key] += f.count

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

18
ответ дан S.Lott 23 November 2019 в 05:21
поделиться

Вы могли создать файл YAML и считать его в использовании PyYaml.

Шаг 1: Создайте файл YAML, "employment.yml":

new jersey:
  mercer county:
    pumbers: 3
    programmers: 81
  middlesex county:
    salesmen: 62
    programmers: 81
new york:
  queens county:
    plumbers: 9
    salesmen: 36

Шаг 2: Читайте это в Python

import yaml
file_handle = open("employment.yml")
my_shnazzy_dictionary = yaml.safe_load(file_handle)
file_handle.close()

и теперь my_shnazzy_dictionary имеет все Ваши значения. Если необходимо было сделать это на лету, можно создать YAML как строку и канал это в yaml.safe_load(...).

24
ответ дан the Tin Man 23 November 2019 в 05:21
поделиться
class AutoVivification(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

Тестирование:

a = AutoVivification()

a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6

print a

Вывод:

{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
187
ответ дан nosklo 23 November 2019 в 05:21
поделиться

collections.defaultdict может быть разделен на подклассы для создания вложенного dict. Тогда добавьте любые полезные итеративные методы к тому классу.

>>> from collections import defaultdict
>>> class nesteddict(defaultdict):
    def __init__(self):
        defaultdict.__init__(self, nesteddict)
    def walk(self):
        for key, value in self.iteritems():
            if isinstance(value, nesteddict):
                for tup in value.walk():
                    yield (key,) + tup
            else:
                yield key, value


>>> nd = nesteddict()
>>> nd['new jersey']['mercer county']['plumbers'] = 3
>>> nd['new jersey']['mercer county']['programmers'] = 81
>>> nd['new jersey']['middlesex county']['programmers'] = 81
>>> nd['new jersey']['middlesex county']['salesmen'] = 62
>>> nd['new york']['queens county']['plumbers'] = 9
>>> nd['new york']['queens county']['salesmen'] = 36
>>> for tup in nd.walk():
    print tup


('new jersey', 'mercer county', 'programmers', 81)
('new jersey', 'mercer county', 'plumbers', 3)
('new jersey', 'middlesex county', 'programmers', 81)
('new jersey', 'middlesex county', 'salesmen', 62)
('new york', 'queens county', 'salesmen', 36)
('new york', 'queens county', 'plumbers', 9)
5
ответ дан the Tin Man 23 November 2019 в 05:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: