Как я могу сделать словарь с точным порядком ключей в Python? - PullRequest
0 голосов
/ 06 марта 2019

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

k = ['date', 'deviceCategory', 'transactionId', 'productSku', 'productName', 'productCategoryHierarchy', 'channelGrouping', 'itemRevenue', 'itemQuantity']

И вот значения для каждого ключа:

v = [datetime.date(2019, 3, 5), 'desktop', 1551740677701, 60104621, '(not set)', 'sale/apartment/alicante/bajo-vinalopo/elx', 'Tráfico de Búsqueda de Pago - Venta', 0.0, 1]

Если я использую набор или пытаюсь создать словарь, используя это:

d = dict(zip(k, v))

Или даже это (то, что я действительно собираюсь сделать):

d = dict(zip(map(lambda x: "ga_%s" % x, k), v))

Я получаю это:

{'ga_itemRevenue': 0.0, 'ga_itemQuantity': 1, 'ga_deviceCategory': 'desktop', 'ga_date': datetime.date(2019, 3, 5), 'ga_channelGrouping': 'Tráfico de Búsqueda de Pago - Venta', 'ga_productSku': 60104621, 'ga_productName': '(not set)', 'ga_productCategoryHierarchy': 'sale/apartment/alicante/bajo-vinalopo/elx', 'ga_transactionId': 1551740677701}

Я знаю, что порядок ключей не имеет значенияв словарях python (по крайней мере, те, которые сделаны с dict()), но мне нужны ключи и их соответствующие значения, чтобы сформировать словарь в том же порядке, который не является алфавитным.Просто ... тот же порядок ключей.

Я пытался создать упорядоченный словарь с collections.OrderedDict(), и порядок - тот, который я хочу, за исключением того факта, что он дает мне список кортежей.Я также пытался «преобразовать» упорядоченный словарь в обычный с помощью этого:

d = json.loads(json.dumps(x))

Но это дает мне ошибку, потому что объект datetime не может быть сериализован (или так он говоритсообщение об ошибке), и мне нужно вот так (как объект datetime), поскольку оно будет записано в таблицу базы данных с пакетом cx_Oracle.

Я также читал о frozenset() но, похоже, мне нужен ранее существующий набор, чтобы «заморозить» его, и как только я создаю набор, это все равно, что пытаться создать словарь.ключи разбросаны по набору, и они нужны мне в том же порядке, в каком они объявлены в массиве ключей.

Как мне этого добиться?

# EDIT 1. Я забылсказать, что это сделано в Python 2.7.x

# EDIT 2. Вот фрагмент кода, с которым у меня проблемы:

reports = response.get("reports", [])

if len(reports) > 0:
  for report in reports:
    rows = report.get("data", {}).get("rows", [])

    if len(rows) > 0:
      k = ga_dimensions + ga_metrics
      o = []

      for row in rows:
        o.append(map(lambda x, y: cast_field_type(x, y), row.get("dimensions", []) + row.get("metrics", [])[0]["values"], k))

      if len(o) > 0:
         # insert all data rows into the table
         for v in o:
           for i in range(0, len(v)):
             if k[i] == "date" and is_date(v[i]):
               v[i] = date(*map(int, v[i].split("-")))
             elif isinstance(v[i], unicode):
               v[i] = v[i].encode("utf-8")

           v = dict(zip(map(lambda x: "ga_%s" % x, k), v))
           cr.execute(q, v)

         # commit all changes
         db.commit()

Этот сценарий извлекает данные из Google Analytics (используя API v4), выводит подходящие типы данных (для хранения базы данных с Oracle) из первой строки данных, перебирает строки данных, так что конкретные поля (в основном, даты и строки Unicode) получают подходящим образомпреобразуется / преобразуется / кодируется перед отправкой в ​​базу данных и после этого фиксирует изменения, чтобы данные записывались по-настоящему.

Я пытаюсь сделать это, потому что сценарий выдает мне эту ошибку при попытке предоставитьсловарь как таковой:

cx_Oracle.DatabaseError: ORA-00932: inconsistent datatypes: expected DATE got NUMBER

И это потому, что данные снабжаются порядком ключей, который отличается от указанного запроса SQL INSERT.

Ответы [ 3 ]

1 голос
/ 06 марта 2019

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

import datetime
import pandas as pd

k = ['date', 'deviceCategory', 'transactionId', 'productSku', 'productName', 'productCategoryHierarchy', 'channelGrouping', 'itemRevenue', 'itemQuantity']

v = [datetime.date(2019, 3, 5), 'desktop', 1551740677701, 60104621, '(not set)', 'sale/apartment/alicante/bajo-vinalopo/elx', 'Tráfico de Búsqueda de Pago - Venta', 0.0, 1]

df = pd.concat([pd.DataFrame(v, k)], axis=1)

# the dataframe
date                                                     2019-03-05
deviceCategory                                              desktop
transactionId                                         1551740677701
productSku                                                 60104621
productName                                               (not set)
productCategoryHierarchy  sale/apartment/alicante/bajo-vinalopo/elx
channelGrouping                 Tráfico de Búsqueda de Pago - Venta
itemRevenue                                                       0
itemQuantity                                                      1

dict = df.to_dict()
results = dict[0]
results

# the dictionary
{'date': datetime.date(2019, 3, 5),
 'deviceCategory': 'desktop',
 'transactionId': 1551740677701,
 'productSku': 60104621,
 'productName': '(not set)',
 'productCategoryHierarchy': 'sale/apartment/alicante/bajo-vinalopo/elx',
 'channelGrouping': 'Tráfico de Búsqueda de Pago - Venta',
 'itemRevenue': 0.0,
 'itemQuantity': 1}
1 голос
/ 06 марта 2019

collections.OrderedDict, кажется, делает то, что вы хотите.Чтобы проиллюстрировать то, что @chepner упомянул о представлении OrderedDict как кортежей, я покажу вам, что я запустил:

#encoding: utf-8
from collections import OrderedDict
import datetime

k = ['date', 'deviceCategory', 'transactionId', 'productSku', 'productName', 'productCategoryHierarchy', 'channelGrouping', 'itemRevenue', 'itemQuantity']
v = [datetime.date(2019, 3, 5), 'desktop', 1551740677701, 60104621, '(not set)', 'sale/apartment/alicante/bajo-vinalopo/elx', 'Tráfico de Búsqueda de Pago - Venta', 0.0, 1]

d = OrderedDict(zip(k,v))
for i in d:
  print('{}: {}'.format(i,d[i]))

print('\n\n')

print(d)

и это был вывод:

date: 2019-03-05
deviceCategory: desktop
transactionId: 1551740677701
productSku: 60104621
productName: (not set)
productCategoryHierarchy: sale/apartment/alicante/bajo-vinalopo/elx
channelGrouping: Tráfico de Búsqueda de Pago - Venta
itemRevenue: 0.0
itemQuantity: 1



OrderedDict([('date', datetime.date(2019, 3, 5)), ('deviceCategory', 'desktop'), ('transactionId', 1551740677701), ('productSku', 60104621), ('productName', '(not set)'), ('productCategoryHierarchy', 'sale/apartment/alicante/bajo-vinalopo/elx'), ('channelGrouping', 'Tr\xc3\xa1fico de B\xc3\xbasqueda de Pago - Venta'), ('itemRevenue', 0.0), ('itemQuantity', 1)])

Итакпохоже, что он ведет себя так, как вы пытались до него добраться.

0 голосов
/ 07 марта 2019

Обратите внимание на две важные вещи:

  • убедитесь, что вы используете переменные связывания (для производительности и безопасности). Это также позволит вам назвать переменные, поэтому порядок данных не должен дело
  • при вставке большого количества строк НАМНОГО эффективнее используйте executeMany(), как описано в https://blogs.oracle.com/opal/efficient-and-scalable-batch-statement-execution-in-python-cx_oracle
...