Счетчик вхождений элемента одного словаря в другой словарь в python - PullRequest
0 голосов
/ 03 марта 2020

У меня есть список вложенных словарей, внутри которых есть другой список словарей, которые меня интересуют. То есть, если у меня есть:

list_of_dicts[0]['data_i_need']

, он содержит следующий словарь:

[
  {
    'key1': ['item1', 'item2', 'item3'],
    'details': 'details'
  },
  {
    'key2': ['item2', 'item4'],
    'details': 'other details'
  }
]

У меня есть еще один большой словарь (d2), имеющий следующую структуру:

{
  'item1': {
    'details': ['detail1', 'detail2',],
    'classes': ['class2'],
  },
  'item2': {
    'details': ['detail1'],
    'classes': ['class1', 'class2'],
  },
}

Я хотел бы добавить еще один словарь в каждый словарь в list_of_dicts, который будет следующим:

{'class1': 2, 'class2': 3}

Т.е. если элемент, соответствующий классу, находится в list_of_dicts[0]['data_i_need'], мне нужно его посчитать. Я хочу l oop через каждый словарь в list_of_dicts.

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

import Counter

for l in list_of_dict:
   for d in l['data_i_need']:
    Counter(d2[d]["classes"])

1 Ответ

1 голос
/ 03 марта 2020

Вы всегда должны определять полные входы и полные выходы для кода, который вы хотите реализовать; этот вопрос не указывает точный ввод и точный вывод, который вы желаете, он пытается смутно объяснить это. Действительно трудно обработать поставленный вопрос: вы должны указать значение semanti c и указать точные значения. «классы» ничего не означают без контекста; «item1» и «key1» ничего не значат. «детали» также бессмысленны как есть. Предоставление подробностей облегчает чтение вопроса и позволяет читателям помочь не только в том, «как мне реализовать эту загадку»: вам нужны хорошие ответы и решения, а не ответы на загадку.

Если я правильно понимаю, вы хотите перебрать все словари в первом списке и обновить этот dict на основе некоторых других критериев. Давайте просто разделим это, передав обе функции новой функции - выполнимо, потому что python dicts передаются по ссылке:

for d in list_of_dicts:
  add_class_counts(d, itemInfo)

(я переименовываю d2 в itemInfo, потому что он имеет по крайней мере немного больше семанти c информации.)

Я предполагаю, что d будет одним словарем, состоящим из:

{
  'data_i_need': [
    {
      'key1': ['item1', 'item2', 'item3'],
      'details': 'some irrelevant details',
    },
    {
       'key2': [...],
       # more?
    }
  ]
}

Я перепутал что у вас key1 и key2. Должны ли мы предположить, что это просто items? Вы должны превратить key1 и key2 из ключей в значение под ключом name, например:

{
  'name': 'key1',
  'items': ['item1', 'item2']
  'details': 'some irrelevant details'
}

Проблема в том, что если вход не структурирован, как это, откуда вы знаете какие key1 и key2 являются этими волшебными именами ключей? Вам нужен список разрешений для других константных ключей, таких как details, который вы бы затем проигнорировали, пытаясь угадать, какой из других ключей является key1:

def name_for_datadict(d):
  # note: untested code.
  allow_list = ['details']
  all_keys = d.keys()
  unknown_keys = [k for k in all_keys if k not in allow_list]
  if len(unknown_keys) == 1: 
     return unknown_keys[0]
  # if it's 0 or greater than 1, we couldn't guess, give up
  raise Exception('invalid data: ' + str(d))

Это уродливо и (намеренно) сломается, если у вас более одного «непостоянного» ключа.

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

Давайте посмотрим; add_class_counts() требуется go через каждый элемент в переданном диктанте:

def add_class_counts(d, itemInfo):
  # expected input:
  # d = {
  #   'name': 'key1',
  #   'items': ['item1', 'item2'],
  # }

  class_counts = {}
  for itm in d['items']:
    class_list = classes_for_item(itmName, itemInfo):
    # TODO: count it somehow

Как мы узнаем, к каким классам относится элемент? Это на самом деле очевидно:

def class_list(itmName, itemInfo):
  # this should return ['class1', 'class2']
  return itemInfo[itemName]['classes']

Как мы это посчитаем?

def add_class_counts(d, itemInfo):
  class_counts = {}
  for itm in d['items']:
    class_list = classes_for_item(itmName, itemInfo):
    for class_name in class_list:
      try:
        class_counts[class_name] += 1
      except: # TODO: limit to the 'key not found' exception which I cannot remember right now
        class_counts[class_name] = 0

  # we've finished counting.
  # update the existing dictionary with the counts.
  d['class_counts'] = class_counts

Примечание: код не проверен, и он делает странные вещи (возможно, вы хотите вернуть class_counts а затем обновить d?). Но это может дать вам базовую c идею.

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

...