Страницы

Поиск по вопросам

Показаны сообщения с ярлыком словари. Показать все сообщения
Показаны сообщения с ярлыком словари. Показать все сообщения

понедельник, 13 апреля 2020 г.

Соответствие между dict.key() и dict.values()

#python #словари

                    
Насколько я понимаю, из-за того, что словари словари - неупорядоченные коллекции,
порядок, в котором идут элементы, никак не гарантируется.

Но можно ли быть уверенным, что наборы dict.keys() и dict.values() будут соответствовать
друг другу?

Т.е., грубо говоря, что d[list(d.keys())[i]] == list(d.values())[i] для любого i
< len(d).
    


Ответы

Ответ 1



Если словарь не модифицировался, то да, можно быть уверенным. http://docs.python.org/2/library/stdtypes.html#dict.items

Ответ 2



есть d.items(), который возвращает кортежи ключ-значение

вторник, 31 марта 2020 г.

Рекурсивная функция для поиска пути в List-ах

#c_sharp #рекурсия #списки #словари


Есть n-ое количество элементов в словаре:

Dictionary> dict = new Dictionary>();


В List лежат ключи связующих словарей. То есть, например, словарь с ключом '1' связывается
со словарями с ключами 1, 6, 8, 10. А словарь с ключом 90 связывается со словарями
с ключами 8, 3, 92, 138. 

dict[1] = new List(){ 87, 6, 8, 10 };
dict[90] = new List() { 8, 3, 92, 138 };


Задача - найти кратчайший путь между словарями dict[1] и dict[90] по их связям. То
есть сначала сравнить все элементы в списке словаря с ключом 1 с 90. 
Потом сравнить по-очереди каждый элемент списка в словаре с ключом '87' с 90, потом
каждый элемент списка в словаре с ключом '6' и так далее, пока не будет достигнуто
совпадение с 90.
Полученный путь нужно запомнить в отдельный List, в котором будут ключи словарей в пути.

Пример:

dict[1] = new List(){ 3, 5 };
dict[3] = new List(){ 1, 8 };
dict[5] = new List(){ 1 };
dict[8] = new List(){ 3, 90 };
dict[90] = new List() { 8 };


Нужно найти кратчайшее расстояние от dict[1] до dict[90]. Сначала сравниваем все
элементы в dict[1] с 90. Элемента 90 в списке словаря '1' нет. Ищем дальше: берём первый
элемент списка словаря с ключом '1' (3) и сравниваем элементы словаря dict[3] с 90.
Элемента 90 в списке словаря '3' нет. Берём следующий элемент списка словаря '1' (5).
Там сравниваем всего один элемент и тоже нет совпадений. 

Теперь углубляемся и рассматриваем элементы словаря '3' как отдельные словари. Т.е.
проверяем dict[1] - ничего нет. Проверяем dict[8] - совпадение. Поиск закончен!

При этом нужно запоминать путь. В качестве вывода использовать

List output = new List();


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

output.Add(1);
output.Add(3);
output.Add(8);
output.Add(90);


Очевидно, нужно использовать рекурсию для прохождения по всем элементам списков.
    


Ответы

Ответ 1



Рекурсию можно использовать, но не нужно. Задача сводится к обходу графа в ширину. Где словари - это вершины графа. А ключи доступа - ребра. Замечу, что это орграф. Извиняйте за введение собственной системы ввода данных, писал, чтобы проверить работоспособность. А раз написал, не грех и поделиться. На вход поступает 2 числа, N - кол-во ключей и M - кол-во записей о этих ключах. В следующих M строках описываются ключи в формате: 1-e число - ключ, последующие через пробел - ключи других словарей. Далее программа требует два числа X и Y. От какого словаря требуется найти путь к другому. Программа выводит кратчайший путь, если таковой существует, иначе "Don't exist". string[] Inp = Console.ReadLine().Split(); // Заносим данные ==>> int N = Convert.ToInt32(Inp[0]), M = Convert.ToInt32(Inp[1]); Dictionary> dict = new Dictionary>(); for (int i = 0; i < N; i++) dict[i] = new List(); for (int i = 0; i < M; i++) { Inp = Console.ReadLine().Split(); int Temp = Convert.ToInt32(Inp[0]) - 1; for (int j = 1; j < Inp.Length; j++) { dict[Temp].Add(Convert.ToInt32(Inp[j]) - 1); } } Inp = Console.ReadLine().Split(); int X = Convert.ToInt32(Inp[0]) - 1, Y = Convert.ToInt32(Inp[1]) - 1; // <<== Все еще заносим Queue Work = new Queue(); // BFS работает через очередь. bool[] Mark = new bool[N]; // Массив, в котором будем помечать посещенные словари int[] Log = new int[N]; // Потребуется для вывода найденного пути bool Exist = false; // Существует ли наш путь вообще Work.Enqueue(X); // см. Алгоритм BFS (обход в глубину) Mark[X] = true; Log[X] = -1; while (Work.Count > 0) { int v = Work.Dequeue(); for (int i = 0; i < dict[v].Count; i++) { if (!Mark[dict[v][i]]) { if (dict[v][i] == Y) Exist = true; Work.Enqueue(dict[v][i]); Mark[dict[v][i]] = true; Log[dict[v][i]] = v; } } } if (Exist) { List output = new List(); // Восстанавливаем путь for (int v = Y; v != -1; v = Log[v]) output.Add(v); output.Reverse(); for (int i = 0; i < output.Count; i++) Console.Write(output[i] + 1 + " "); Console.WriteLine(); } else Console.WriteLine("Don't exist"); Вот пример работы: Входные данные: 100 6 1 2 3 4 5 5 2 3 1 45 42 13 54 42 13 3 45 42 54 1 13 Выходные данные: 1 3 45 13 Надеюсь, помог.

пятница, 28 февраля 2020 г.

Особенности архитектуры StringDictionary

#net #словари


Предыстория:

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

Недавно же я разбирал один код, который выдавал NullReferenceException там, где его
по логике вещей быть не могло.

Отдебажив его, я обнаружил следующую вещь:
Человек использовал в своем коде StringDictionary (к слову, весьма радует, ибо я
знаю внушающее количество .NET программистов, которые ни разу не заглядывали в System.Collections.Specialized)
и забыл поставить проверку на существование строки по указанному ключу, тем самым словарь
молча возвращал null и чуть позже код падал, так как строки со значением null должны
были отсутствовать внутри словаря и проверка на это не подразумевалась

В случае со стандартным Dictionary и созданием указанного выше исключения эту ошибку
отловить было бы куда проще, однако у StringDictionary немного иная "идеология", так
что по несуществующему ключу он возвращает null (который, к слову, без вызова метода
ContainsKey неотличим от существующей по указанному ключу строки с null-значением)



Собственно, сам вопрос:

Почему при проектировании StringDictionary отошли от архитектуры привычного всем
словаря и вместо логичного выброса соответствующего исключения сделали просто возвращение
null?

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


Ответы

Ответ 1



Все гораздо проще - Specialized - это рудимент до-генериковского .net 1.1. Генерик-реализация Dictionary не может возвращать null для несществующих значений - она должна работать и с reference types, и с value types, причем работать одинаково. Вернуть же null для value type несоколько затруднительно. На момент появления генериков классы из Specialized активно использовались, и их поведение сохранили ради совместимости. В современном проекте единственая причина для работы с Specialized - это необходимость интеграции с legacy кодом. Они не реализуют новых генерик интерфейсов, они ведут себя странно и непредсказуемо (например, StringDictionary приводит ключи к lowercase), и они могут быть медленее новых генериков даже на базовых операциях, например: [Benchmark] public StringDictionary StringDictionary() { StringDictionary stringDictionary = new StringDictionary(); foreach (var i in Enumerable.Range(0, 1000000)) { stringDictionary[i.ToString()] = i.ToString(); } return stringDictionary; } [Benchmark] public Dictionary NewDictionary() { var stringDictionary = new Dictionary(); foreach (var i in Enumerable.Range(0, 1000000)) { stringDictionary[i.ToString()] = i.ToString(); } return stringDictionary; } Method | Mean | Error | StdDev | ----------------- |---------:|---------:|---------:| StringDictionary | 694.0 ms | 5.631 ms | 5.268 ms | NewDictionary | 280.2 ms | 5.369 ms | 5.022 ms |

понедельник, 24 февраля 2020 г.

Нужен способ получения случайных английских слов. Как лучше это реализовать?

#c_sharp #unity3d #словари


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


Ответы

Ответ 1



Реализация: Самое простое, что приходит в голову это хранить слова в txt файле. Загружаем строку из файла. Разбиваем ее в зависимости от разделителя для слов, который был использован. Складываем это все в массив и дальше пользуемся как угодно. Скачать: Есть частотные словари, вот например такой http://www.wordfrequency.info/100k.asp

Ответ 2



Списки слов есть в интернете, и легко гуглятся. Поэтому вы можете подсчитать общее количество слов/строк в файле, и в нужный момент просто брать строку со случайным номером. Небольшой трюк состоит в том, что обычно искать строку по номеру невозможно без предварительного чтения всех предыдущих строк. Чтобы обойти это, подсчитайте максимальную длину слова в вашем файле, и дополните все слова пробелами до этой максимальной ширины. Теперь ваши строки все одинакового размера (разумеется, если вы используете Encoding.Unicode, а не Encoding.UTF8: английские слова могут содержать символы вне ASCII), и вы можете просто найти смещение начала строки в файле. Ну или если в вашем словаре несчастных 20 тысяч слов (размером со словарный запас Пушкина), можно не париться с оптимизацией хранения, и считать весь словарь в память один раз при старте программы.

суббота, 15 февраля 2020 г.

Обращение к элементам массива из словарей. Десериализация Json строки

#c_sharp #json #словари


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


  {"response":{"map_width":80,"map_height":80,"map_sp":5541,"objects":[{"type":1,"health":100},{"type":1,"health":100},{"type":1,"health":100},{"type":1,"health":100},{"type":1,"health":100}]}


Я могу спокойно получить все данные, кроме objects.
Объявление массива словарей такое: public System.Collections.Generic.Dictionary[] Field_Params;.
Попытка получения данных из массива Field_Params This_Field.Field_Params[0]["type"]
безуспешна т.к. я не могу обратиться к конкретному словарю.
Помогите, пожалуйста. Либо с тем, как получить данные из конкретного словаря в массиве,
либо как лучше десериализовать возвращаемую сервером строку.
Код скрипта, который получает данные с сервера:  

using System.Net;
using Newtonsoft.Json;
using UnityEngine;
using System.Collections.Generic;

public class Web_Queries : MonoBehaviour
// Класс Веб- запросов
{
    public class Web_Field
    // Поле с данными, получаемыми с сервера
    {
        // Ответ с сервера
        [JsonProperty("response")]
        public Dictionary[] Response;
        // Ответ с сервера
        [JsonProperty("debug")]
        public string Description;
    }

    public Web_Field Get (string Url)
    // Get- запрос
    {
        // Объявляем новый экземпляр класса Web_Field
        Web_Field New_WF = new Web_Field();
        // Проверка подлинности сертефиката сайта
        ServicePointManager.ServerCertificateValidationCallback = delegate { return
true; };
        string Common_Response;
        // Создание нового объекта класса
        using (var Connection = new WebClient())
        {
            // Запрос на сайт
            Common_Response = Connection.DownloadString(Url);
        }
        New_WF = JsonConvert.DeserializeObject(Common_Response);
        // Вернуть ответ с сервера
        return New_WF;
    }
}

    


Ответы

Ответ 1



Вариант 1: Возьмем ваш JSON и прогоним его через этот сайт. В ответ получаем структуру необходимых классов для грамотной десериализации JSON. Я смотрю у вас стоит JSON.NET, поэтому используем его, десериализируем строку в наш объект: var json = JsonConvert.DeserializeObject(file);. Дальше без проблем можно получить доступ ко всему, что нам необходимо, например циклом пройтись по все данным из objects. В итоге получаем что то вроде: public class Object { public int type { get; set; } public int health { get; set; } } public class Response { public int map_width { get; set; } public int map_height { get; set; } public int map_sp { get; set; } public List objects { get; set; } } public class RootObject { public Response response { get; set; } } var file = "{\"response\":{\"map_width\":80,\"map_height\":80,\"map_sp\":5541,\"objects\":[{\"type\":1,\"health\":100},{\"type\":1,\"health\":100},{\"type\":1,\"health\":100},{\"type\":1,\"health\":100},{\"type\":1,\"health\":100}]}}"; var json = JsonConvert.DeserializeObject(file); foreach (var item in json.response.objects) { Console.WriteLine($"Type: {item.type}. Health {item.health}"); } Вариант 2 (без использования классов): Парсим строку в JObject, методом Parse. Получаем небходимые данные, путем добавления некого индекса к нашему JObject. Сам код: var file = "{\"response\":{\"map_width\":80,\"map_height\":80,\"map_sp\":5541,\"objects\":[{\"type\":1,\"health\":100},{\"type\":1,\"health\":100},{\"type\":1,\"health\":100},{\"type\":1,\"health\":100},{\"type\":1,\"health\":100}]}}"; var json = JObject.Parse(file); foreach (var item in json["response"]["objects"]) { Console.WriteLine($"Type: {item["type"]}. Health {item["health"]}"); } Второй вариант хорошо подойдет маленькой утилите, которая использует небольшие данные JSON, на большом проекте его будет трудно изменять/масштабировать под сервер, ибо изменится значение на сервере - придется все строки переписывать и во всем коде. В первом варианте у вас есть структура, классы, которые соответствую тому, что есть на сервере в формате JSON, изменится у сервера что либо - быстро подправили класс и в нужном месте исправили ошибки. Что выбирать - решать вам.

пятница, 14 февраля 2020 г.

Можно ли сохранить экземпляр TDictionary целиком, включая хэши?

#delphi #оптимизация #хеширование #словари #биоинформатика


Учитывая, что теперь можно спокойно выделять большие объемы памяти внутри TMemoryStream,
я вернулся к идее хранения данных геномных исследований, используемых нами внутри TDictionary
в файле для будущего повторного использования. Класс определен так:

type
  PosIndex = packed record
     chr, pos:integer;
  end;
  PosIndexData = record
    gname, rname, promoter: string;
    count:array[0..NOfTissues-1] of byte;
  end;

TPosDict = class (TDictionary)
 private
   procedure SaveToStream(stream: TStream);
   procedure LoadFromStream(stream: TStream);
 public
   procedure SaveToFile(filename:string);
   procedure LoadFromFile(filename:string);
   procedure LoadFromZip(AFileName, InnerName: string);
   procedure SaveToZip(AFileName, InnerName: string);
end;


Предупреждая вопросы и комментарии в стиле "Зачем нужен TDictionary, когда есть базы
данных?", сразу скажу: у нас мобильное (не в плане телефона, а в плане, что оно часто
запускается где попало) приложение, мы не можем использовать стационарный сервер БД,
как коллега в своём вопросе Как оптимизировать таблицы/запрос в MySQL?, а работа с
файловыми БД с нашими объёмами данных, увы, крайне медленна. А вот с TDictionary поиск
происходит пусть не мгновенно, но для нас вполне подходяще по времени.

Запись в поток (этот метод затем используют и SaveToFile и SaveToZip) происходит так:

procedure TPosDict.SaveToStream(stream: TStream);
var
  writer: TWriter;
  ps:PosIndex;
  pid:PosIndexData;
  l:integer;
begin
  writer := TWriter.Create(stream, 4096);
  l:=sizeof(pid.count);
  try
    writer.WriteListBegin;
    for ps in Self.Keys do
      begin
        pid:=Items[ps];
        writer.WriteInteger(ps.chr);
        writer.WriteInteger(ps.pos);
        writer.WriteString(pid.gname);
        writer.WriteString(pid.rname);
        writer.WriteString(pid.promoter);
        writer.Write(pid.count,l);
      end;
    writer.WriteListEnd;
  finally
    writer.Free;
  end;
end;


Метод быстр, гигабайтные данные сохраняются быстро даже в ZIP-файл. А вот считывание
из файла крайне медленно из-за того, что данные добавляются во вновь созданный TDictionary,
происходит хэширование и проверка на уникальность:

procedure TPosDict.LoadFromStream(stream: TStream);
var
  reader: TReader;
  ps:PosIndex;
  pid:PosIndexData;
  l:integer;

begin
  Clear;
  l:=sizeof(pid.count);
  reader := TReader.Create(stream, 9192);
  try
    reader.ReadListBegin;
    while not reader.EndOfList do
    begin
       ps.chr:=reader.ReadInteger;
       ps.pos:=reader.ReadInteger;
       pid.gname:=reader.ReadString;
       pid.rname:=reader.ReadString;
       pid.promoter:=reader.ReadString;
       reader.Read(pid.count,l);
       Add(ps,pid); // вот это всё тормозит!!!
    end;
    reader.ReadListEnd;
  finally
    reader.Free;
  end;
end;


Избежать этого, как я понимаю, нельзя. Но ведь это уже было сделано, когда объект
существовал ранее, все хэши уже были созданы и работали. Появилась идея: можно ли при
сохранении TDictionary как-то сохранить объект целиком, включая хэши, а затем так же
восстановить из файла, чтобы не тратилось время на перехэширование. Ну, или другие
идеи, как убрать бутылочное горло при восстановлении данных.
    


Ответы

Ответ 1



Особенность TDictionary в том, что когда заканчивается ёмкость под хэши, он увеличивает размер и в этот момент происходит перехэширование всей имеющийся (на данный момент) коллекции. Поэтому если заранее примерно известен размер коллекции, то этот размер умноженный на 2-3 можно поставить в capacity.

четверг, 13 февраля 2020 г.

Пройтись по ключам начиная с определенного. Словарь python

#python #python_3x #словари


Есть следующий код:

dic = {'A':213, 'B':1424, 'F':412, 'Gs':asf}
for key in dic:
    print(key)


Как можно проитерировать его, начиная со второго ключа?
Или, например, с ключа F?
    


Ответы

Ответ 1



В CPython реализации Python 3.6 элементы словаря сохраняют порядок данный им при создании. Это деталь реализации, не гарантированная стандартом языка. Начиная с Python 3.7 - это гарантированное поведение для любой реализации Python: the insertion-order preservation nature of dict objects has been declared to be an official part of the Python language spec. Соответственно, для Python 3.7+ вы можете сделать: In [6]: list(dic.keys())[2:] Out[6]: ['F', 'Gs'] Для более ранних версий вы можете воспользоваться OrderedDict, как вам уже посоветовал @Хачатур Саркисян: In [9]: from collections import OrderedDict In [10]: odic = OrderedDict(dic) In [11]: list(odic.keys())[2:] Out[11]: ['F', 'Gs']

Ответ 2



Словари в Python являются неупорядоченными структурами данных. Обращение по ключу происходит за счет хэширования. Именно поэтому ваш вопрос не имеет под собой основания. Чтобы реализовать нечто похожее используйте структуру данных OrderedDict.

Ответ 3



Как уже было сказано, ключи в словаре не имеют определенного порядка. Если нужно пройтись по ключам в лексикографическом порядке, то такое решение: Сортируем ключи, потом проходимся по ним. Пока не встретили ключ F - ничего не печатаем. dic = {'A': 213, 'B': 1424, 'F': 412, 'Gs': 'asf'} print_key = False for key in sorted(dic): if key == 'F': print_key = True if print_key: print(key) Вывод: F Gs

Ответ 4



num_of_row = 2 for i, x in enumerate(dic): if i>=num_of_row: print(i,x)

воскресенье, 9 февраля 2020 г.

Автоматизация добавления вложенных словарей в словарь

#python #python_3x #словари


Подскажите пожалуйста, как работает добавление в словари?

Например, есть пустой словарь:

b = {}


Я хочу добавить, 

b['id']['type'] = 5


Получаю ошибку:


Traceback (most recent call last):
  File "", line 1, in 
    b['id']['type'] = 5
KeyError: 'id'



Может есть какой-то другой способ записи, кроме:

b['id'] = {'type': 5}

    


Ответы

Ответ 1



Используйте defaultdict: from collections import defaultdict b = defaultdict(dict) b['id']['type'] = 5 print(b) # defaultdict(dict, {'id': {'type': 5}}) Тут вы указываете, что создаете словарь, каждое значение которого по-умолчанию - пустой словарь.

Ответ 2



Для создания новых значений с глубокой степенью вложенности можно воспользоваться модулем dpath: import dpath # pip install dpath b = {} dpath.util.new(b, '/id/type', 5) результат: In [79]: b Out[79]: {'id': {'type': 5}} добавляем еще один вложенный словарь: dpath.util.new(b, '/id/sub1/sub2/sub3/val', [1,2,3]) результат: In [81]: b Out[81]: {'id': {'type': 5, 'sub1': {'sub2': {'sub3': {'val': [1, 2, 3]}}}}}

Преобразование списка в словарь

#python #python_3x #словари #dict


Получаю список с данными из БД в таком виде. Kоличество словарей в списке может быть
произвольным: 

 result = [{'name': 'CPG_17_002', 'dnorpattern': '94009'}, 
           {'name': 'CPG_17_002', 'dnorpattern': '94011'}, 
           {'name': 'CPG_17_001', 'dnorpattern': '94004'}, 
           {'name': 'CPG_17_001', 'dnorpattern': '94005'}, 
           {'name': 'CPG_17_000', 'dnorpattern': '94007'}, 
           {'name': 'CPG_17_000', 'dnorpattern': '94010'}, 
           {'name': 'CPG_17_000', 'dnorpattern': '94012'}]


Для дальнейшей обработки и представления данных, данный список необходимо переобразовать
в словарь вида:      

{'CPG_17_002': ['94009', '94011'],
 'CPG_17_001': ['94004', '94005']
 'CPG_17_000': ['94007', '94010', '94012']
}


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


Ответы

Ответ 1



result = [{'name': 'CPG_17_002', 'dnorpattern': '94009'}, {'name': 'CPG_17_002', 'dnorpattern': '94011'}, {'name': 'CPG_17_001', 'dnorpattern': '94004'}, {'name': 'CPG_17_001', 'dnorpattern': '94005'}, {'name': 'CPG_17_000', 'dnorpattern': '94007'}, {'name': 'CPG_17_000', 'dnorpattern': '94010'}, {'name': 'CPG_17_000', 'dnorpattern': '94012'}] d = {} for i in result: if i['name'] not in d: d[i['name']] = [i['dnorpattern']] else: d[i['name']].append(i['dnorpattern']) print(d) #{ # 'CPG_17_002': ['94009', '94011'], # 'CPG_17_001': ['94004', '94005'], # 'CPG_17_000': ['94007', '94010', '94012'] #}

Ответ 2



Можно использовать метод словаря .get res_dict = {} for item in result: name = item['name'] value = item['dnorpattern'] res_dict[name] = res_dict.get(name, []) + [value] либо вместо словаря взять collections.defaultdict from collections import defaultdict res_dict = defaultdict(list) for item in result: name = item['name'] value = item['dnorpattern'] res_dict[name].append(value)

Ответ 3



Решение с использованием Pandas: import pandas as pd # pip install pandas df = pd.DataFrame(result) res = df.groupby("name")["dnorpattern"].apply(lambda x: x.to_list()).to_dict() Результат: In [15]: res Out[15]: {'CPG_17_000': ['94007', '94010', '94012'], 'CPG_17_001': ['94004', '94005'], 'CPG_17_002': ['94009', '94011']} Пошагово: In [16]: df Out[16]: dnorpattern name 0 94009 CPG_17_002 1 94011 CPG_17_002 2 94004 CPG_17_001 3 94005 CPG_17_001 4 94007 CPG_17_000 5 94010 CPG_17_000 6 94012 CPG_17_000 In [17]: df.groupby("name")["dnorpattern"].apply(lambda x: x.to_list()) Out[17]: name CPG_17_000 [94007, 94010, 94012] CPG_17_001 [94004, 94005] CPG_17_002 [94009, 94011] Name: dnorpattern, dtype: object In [18]: df.groupby("name")["dnorpattern"].apply(lambda x: x.to_list()).to_dict() Out[18]: {'CPG_17_000': ['94007', '94010', '94012'], 'CPG_17_001': ['94004', '94005'], 'CPG_17_002': ['94009', '94011']}

среда, 5 февраля 2020 г.

Как сделать словарь из двух списков?

#python #pandas #словари


Итак , у меня есть два списка uniq и fifa(по длине одинаковы). Мне нужно , чтобы
каждому элементу списка uniq был наследован каждый элемент списка uniq. 

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


Ответы

Ответ 1



uniq = [1,2,3,4,5] fifa = ['a','b','c','d','e'] uniq_and_fifa = dict(zip(uniq, fifa))

Ответ 2



Судя по описанию задачи и метке Pandas вам нужен Pandas.Series: In [48]: uniq = np.arange(1, 11) In [49]: fifa = np.random.choice(list('abcdefgh'), 10) In [50]: s = pd.Series(fifa, index=uniq) In [51]: s Out[51]: 1 b 2 c 3 b 4 d 5 f 6 e 7 a 8 a 9 c 10 h dtype: object

Как объединить два списка/кортежа словарей (например списки записей БД) в Python

#python #python_3x #python_2x #словари #объединение


Имеется два списка словаря:

Первый:

x = {'title':'[Лада]', 'prise':'[70000]', 'status':'[Непродана]'},{'title':'[нисан]',
'prise':'[70000]', 'status':'[Непродана]'}


Второй:

y = {'title':'[Лада]', 'prise':'[70000]', 'status':'[Продана]'},{'title':'[БМВ]',
'prise':'[70000]', 'status':'[Непродана]'}


Желаемый результат:

 z = {'title':'[Лада]', 'prise':'[70000]', 'status':'[Продана]'},{'title':'[нисан]',
'prise':'[70000]', 'status':'[Непродана]'}, {'title':'[БМВ]', 'prise':'[70000]', 'status':'[Непродана]'}

    


Ответы

Ответ 1



Pandas замечательно справляется с подобными задачами: import pandas as pd def merge(*args): return (pd.concat([pd.DataFrame(x if isinstance(x, list) else list(x)) for x in args], ignore_index=True) .drop_duplicates('title', keep='last')) def merge2(*args): return (pd.concat([pd.DataFrame(x if isinstance(x, list) else list(x)) for x in args], ignore_index=True) .drop_duplicates('title', keep='last') .to_dict('records')) В виде Pandas DataFrame: In [72]: merge(x, y) Out[72]: prise status title 1 [70000] [Непродана] [нисан] 2 [70000] [Продана] [Лада] 3 [70000] [Непродана] [БМВ] В виде списка словарей: In [73]: merge2(x, y) Out[73]: [{'prise': '[70000]', 'status': '[Непродана]', 'title': '[нисан]'}, {'prise': '[70000]', 'status': '[Продана]', 'title': '[Лада]'}, {'prise': '[70000]', 'status': '[Непродана]', 'title': '[БМВ]'}]

Ответ 2



z = {} for d in sorted((d for o in (x, y) for d in o), key=lambda d: d['status'] == '[Непродана]'): t = d['title'] if t not in z: z[t] = d z = list(z.values()) print('\n'.join(map(str, z))) # {'title': '[Лада]', 'prise': '[70000]', 'status': '[Продана]'} # {'title': '[нисан]', 'prise': '[70000]', 'status': '[Непродана]'} # {'title': '[БМВ]', 'prise': '[70000]', 'status': '[Непродана]'}

Ответ 3



Обратите внимание первый это не словарь а список, содержащий словари. Объединить словари: x = {'title':'[Лада]', 'prise':'[70000]', 'status':'[Непродана]'},{'title':'[нисан]', 'prise':'[70000]', 'status':'[Непродана]'} y = {'title':'[Лада]', 'prise':'[70000]', 'status':'[Продана]'},{'title':'[БМВ]', 'prise':'[70000]', 'status':'[Непродана]'} x.update(y) print "Value : %s" % x

четверг, 23 января 2020 г.

Python requests: при указании заголовков запросы по сети идут в случайном порядке

#python #requests #словари


Использую библиотеку requests для выполнения запросов по сети. Но возникла проблема.
Когда указываю заголовки, то они идут в рандомном порядке
>>> headers = {'Connection':'keep-alive',
           'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
           'Accept-Encoding':'gzip,deflate,sdch',
           'Accept-Language':'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4',
           'Cache-Control':'max-age=0',
           'Origin':'http://site.ru',
           'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/29.0.1547.0 Safari/537.36'}
>>> headers
{'Origin': 'http://site.ru', 'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4',
'Accept-Encoding': 'gzip,deflate,sdch', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/29.0.1547.0 Safari/537.36', 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0'}

Origin перескакивает в самое начало. Суть в том, что сервер восприимчив к подобным
переменам, и заголовки надо отправлять в строго определенном порядке. Вычитал что это
проблема возникает из за того что используется словарь. Однако как я понял, requests
принимает header только в таком виде.
Подскажите, как можно решить данную проблему?
PS возможности вмешиваться в работу сервера нет.    


Ответы

Ответ 1



И Вы и Python и Header'ы в HTTP используют словарь {"ключей":"значений"}, не имеет никакого смысла указывать Header'ы по другому. Меняйте серверную часть, которая нормально сможет обращаться к заголовкам по их "ключу". Что это за серверная часть, у которой важен порядок словаря? Словарь на то и словарь, чтобы обращаться к значению по его ключу. И я вас уверяю, даже не пытайтесь сдерживать порядок словаря, это невозможно, при передаче данных порядка не будет. Есть конечно разного рода сортировка для словарей, но она не применима конкретно к Header'ам, так как Header'ы сами по себе сконструированы по принципу словаря.

Ответ 2



Порядок http-заголовков не гарантирован (ни в спецификации, ни на практике). Заголовки могут быть переставлены при транспортировке через интернет. Хотя для целей спецификации (Internet Message Format) заголовки не следует переставлять в общем, а некоторые заголовки не должны переставляться вообще. См. Сохраняет ли HTTPMessage порядок ключей? возможности вмешиваться в работу сервера нет. Чтобы упорядочить свои заголовки, достаточно их как collections.OrderedDict передать (так как dict в Питоне не упорядочен). Если вы хотите также свой порядок для заголовков, которые requests самостоятельно выставляет, то можно их переопределить на Session объекте. См. Header Ordering: #!/usr/bin/env python3 from collections import OrderedDict import requests session = requests.Session() session.headers = OrderedDict([ ('Connection', 'keep-alive'), ('Accept-Encoding', 'gzip,deflate'), ('Origin', 'example.com'), ('User-Agent', 'Mozilla/5.0 ...'), ]) # ... custom_headers = OrderedDict([('One', '1'), ('Two', '2')]) req = requests.Request('GET', 'https://httpbin.org/get', headers=custom_headers) prep = session.prepare_request(req) print(*prep.headers.items(), sep='\n') Вывод: ('Connection', 'keep-alive') ('Accept-Encoding', 'gzip,deflate') ('Origin', 'example.com') ('User-Agent', 'Mozilla/5.0 ...') ('One', '1') ('Two', '2') Порядок заголовков сохранён.

Как строятся справочные системы?

#sql #база_данных #алгоритм #словари


Имеется какой-то справочник на N адресов к которому обращается многопользователей.

Казалось бы, размещай справочник в СУБД и все...

Но, обычно, справочные системы предлагают поиск по частичному совпадению => от пользователей
идет множество LIKE запросов, которые СУБД не может оптимизировать так как индексы
не работают.

Вот как выходят из такой ситуации? Неужели все решает покупкой более мощного железа?
    


Ответы

Ответ 1



Есть N-граммный поиск. Он воспринимает строку как набор отдельных подстрок длины N, а показателем релевантности служит число таких подстрок, общих между документом и поисковым запросом. Такой подход позволяет обнаруживать мелкие опечатки в словах или находить слова только по кусочку сколько-нибудь существенной (от N+1) длины. Реализаций достаточно, есть выбор. Есть N-граммный токенизатор в ElasticSearch. Есть и в Apache Solr. В Sphinx N-граммный поиск можно включить (утверждается, что он имеет смысл для корейского, японского и китайского, где беда с разделением на слова). Как видно, есть практически во всех известных поисковых серверах, и если вам нужен действительно мощный поиск, лучше воспользоваться разработанным специально для этой цели продуктом. Покопавшись в инструкциях к выбранному, можно найти и другие алгоритмы, которые, возможно, вам понравятся больше. А теперь что-нибудь менее обычное. Для PostgreSQL имеется модуль триграммного поиска (pg_trgm). Как можно догадаться, это N-граммный поиск, где N=3. Для него практически необходим отдельный индекс GIN или GiST, составленный по классу операторов из этого модуля. GIN довольно большой по объёму, не слишком быстро обновляется, но быстр для поиска; тогда как GiST компактнее и быстрее обновляется, но может давать ложные совпадения. Поэтому для редко обновляемых данных GIN оптимальнее. Это неплохой вариант, если у вас уже используется PostgreSQL, он не особенно нагружен (или есть возможность это обеспечить) и от поиска не нужна большая интеллектуальность. У него есть и реализация полнотекстового поиска, но это уже не относится к N-граммному.

среда, 22 января 2020 г.

Как объединить несколько списков в список словарей?

#python #python_3x #list #словари


Допустим, есть 3 списка:

names = ['A', 'B', 'C']
numbers = ['5','10','15']
colors = ['red','white','blue']


Как соединить эти 3 списка в словари вида:

{'name': A, 'number': 5, 'color': red}
{'name': B, 'number': 10, 'color': white}
{'name': C, 'number': 15, 'color': blue}

    


Ответы

Ответ 1



names = ['A', 'B', 'C'] numbers = ['5','10','15'] colors = ['red','white','blue'] keys = ['name', 'number', 'color'] zipped = zip(names, numbers, colors) dicts = [dict(zip(keys, values)) for values in zipped] print(dicts) # Напечатает: # [{'name': 'A', 'color': 'red', 'number': '5'}, # {'name': 'B', 'color': 'white', 'number': '10'}, # {'name': 'C', 'color': 'blue', 'number': '15'}]

Как проверять слова Русского языка?

#разработка_игр #поиск #любой_язык #словари


Для игры типа «Эрудита» надо проверять, есть ли составленное игроком слово в словаре,
и соответствует ли оно требованиям: именительный падеж, единственное число.
Наверное, достаточно раздобыть текстовый файл со словами через разделитель, и в нём
искать. Кстати, может, есть некий формат, более удобный для поиска? Дерево, сортировка,
всё такое?
Основной вопрос — как расширить набор правил? Разрешить, например, все падежи, множественное
число, глаголы во всех временах.     


Ответы

Ответ 1



На мой взгляд, какого-то лёгкого или средней сложности способа вы врядли найдёте. Разве что, пропишите все возможные варианты в БД или файле. С падежами - проще. Можно было бы прописать корни слов и отдельно возможные суфиксы, окончания слов и т.д. Но и тут засада. Возьмём для примера слова "хэшкод" и "конь". Как проверить правильность написанных слов, если в дательном падеже первое слово будет "хэшкодУ", а второе - "конЮ"? Вопрос риторический. С глаголами и их временами ещё печальней. Берём: "ехать" и "идти". В неопределенном времени (1-е лицо) получаем "езжу" и "хожу". Тут даже логики не просматривается. Вывод: "Велик и могуч русский язык, но под PHP не заточен". P.S. Кстати, тут неподалеку есть еще один форум (Русский язык). Возможно, что там могут кое-что дельное подсказать.

Ответ 2



Я думаю стоит конвертировать словарь в отдельную SQL таблицу для каждой части речи: Например для имен существительных могут быть такие поля: ID, Приставка, Корень, Суффикс, Окончание, Падеж, Род, Все слово, Одушевлённость, Число(единственное множественнно),Склонение, Нарицательность, Это же слово по умолчанию(ед число именительный падеж) И далее просто делать SELECT к этой таблице. Другой вопрос как получить эту таблицу из текстового файла, придется писать очень нетривиальный парсер учитывающий морфологию.

воскресенье, 5 января 2020 г.

Dictionary comprehensions синтаксис python

#python #словари #dict #syntax


Допустим, у меня появилось 2 списка, в одном лежат ключи, в другом их значения. Соответствие
поиндексное (1:1,2:2)

keys = []
values = []


Мне при помощи генератора словарей нужно создать словарь, ключом которого является
keys[i], а значением values[i].

Подскажите правильный синтаксис этого действия, всё, что пока получилось:

{k:v for k in keys for v in values} 


Oднако, данный синтаксис создаёт вложенный список и проходит по нему полностью.
Mогу ли я как-то осуществить синхронный забор данных из списков?
    


Ответы

Ответ 1



В том случае если число элементов в keys и values совпадает можно воспользоваться встроенной функцией zip(): In [1]: keys = list("abcd") In [2]: values = [11,12,13,14] dictionary comprehension: In [3]: d = {k:v for k,v in zip(keys, values)} In [4]: d Out[4]: {'a': 11, 'b': 12, 'c': 13, 'd': 14} dict() конструктор: In [5]: d2 = dict(zip(keys, values)) In [6]: d2 Out[6]: {'a': 11, 'b': 12, 'c': 13, 'd': 14} если число элементов не совпадает, то не все элементы попадут в итоговый словарь: In [14]: values = [11, 12, 13] In [15]: keys Out[15]: ['a', 'b', 'c', 'd'] In [16]: values Out[16]: [11, 12, 13] In [17]: d3 = dict(zip(keys, values)) In [18]: d3 Out[18]: {'a': 11, 'b': 12, 'c': 13} ключ d не попал в словарь In [19]: d4 = {k:v for k,v in zip(keys, values)} In [20]: d4 Out[20]: {'a': 11, 'b': 12, 'c': 13} если в результирующем словаре должны быть все элементы, то можно воспользоваться itertools.zip_longest(): In [21]: from itertools import zip_longest In [22]: d5 = dict(zip_longest(keys, values)) In [23]: d5 Out[23]: {'a': 11, 'b': 12, 'c': 13, 'd': None} # NOTE: -------------------------> ^^^^^^^^

четверг, 2 января 2020 г.

Перебор ключ-значение в 2-х и более словарях и запись совпадения в новый словарь через *args

#python #python_3x #список #словари


Имеется два словаря, нужно перебрать ключ-значение в обоих словарях.
Сравнить если одинаковые ключ-значения с помощью цикла for и параметра *args. Добавить
в новый словарь одинаковые найденные ключ-значения.

operator_one = { 2: 'break',
         1: 'pass',
         3: 'print',
         4: 'yield',
         5 :'try' ,
         }


operator_two = { 1: 'pass',
         2:'global',
         3: 'yield',
         4: 'print',
         5: 'try',
         }

def operator_important(farg, *args):
    """Перебор ключ-значения в двух словарях при помощи args и записи в новый словарь."""
    operator_main = dict()             # создание словаря и запись в перем
    print("vocabulary_one:", farg)     # вывод первого аргумента
    for key, value in args:            # перебор ключ-значение в обоих словарях
        print("vocabulary_two:", arg)  # вывод второго аргумента
        if key in args and value == args[key]: # если ключ-значение равно аргументу
ключ-значение, то создаем новый словарь с ключом и значение
            operator_main[key] = value # добавляем в нов. словарь найденное  ключ-значение,
которое совпало


Ошибка: 


  ValueError: too many values to unpack (expected 2)

    


Ответы

Ответ 1



У меня вот так получилось: operator_one = {2: 'break', 1: 'pass', 3: 'print', 4: 'yield', 5: 'try', } operator_two = {1: 'pass', 2: 'global', 3: 'yield', 4: 'print', 5: 'try', } operator_three = {1: 'pass', 2: 'global', 3: 'yield', 4: 'print', 5: 'try', } def operator_important(*args: dict): operator_main = dict() # Создаем пустой словарь for key, value in args[0].items(): # Для ключа и значения из первого словаря... check = True # Устанавливаем флаг проверки в значение "Истина" for i in range(1, len(args)): # Проверяем все словари на совпадение if key not in args[i] or value != args[i][key]: # Если ключ отсутствует в другом словаре # или его значение отлично от проверяемого check = False # Устанавливаем флаг в значение "Ложь" break # И прерываем проверку ключа if check: # Если флаг сохранил значение "Истина" (То есть ключ присутствует во всех проверяемых словарях # и значения ключа во всех словарях равны operator_main[key] = value # Добавляем ключ и значение в новый словарь return operator_main print(operator_important(operator_one, operator_two, operator_three)) Немного упростил функцию: def operator_important(*args: dict): operator_main = dict() # Создаем пустой словарь for key, value in args[0].items(): # Для ключа и значения из первого словаря... for i in range(1, len(args)): # Проверяем все словари на совпадение if key not in args[i] or value != args[i][key]: # Если ключ отсутствует в другом словаре # или его значение отлично от проверяемого break # Прерываем проверку ключа else: # Если цикл не прерывался (То есть ключ присутствует во всех проверяемых словарях # и значения ключа во всех словарях равны operator_main[key] = value # Добавляем ключ и значение в новый словарь return operator_main

Ответ 2



Вы можете послать параметры в функцию с помощью распаковки, привожу возможные варианты для это функции: operator_one = { 2: 'break', 1: 'pass', 3: 'print', 4: 'yield', 5 :'try' , } operator_two = { 1: 'pass', 2:'global', 3: 'yield', 4: 'print', 5: 'try', } def my_dict(d1, d2): d3 = dict() for k in d1: if k in d2 and d1[k] == d2[k]: d3[k] = d1[k] return d3 print (my_dict(*(operator_one, operator_two))) print (my_dict(operator_one, *(operator_two, ))) print (my_dict(operator_one, operator_two, *())) # {1: 'pass', 5: 'try'} Если вы хотите посылать неограниченное количество словарей в функцию то можно так: operator_three = { 1: 'qwerty', 2:'global', 3: 'yield', 4: 'print', 5: 'try', } def my_dict(*d_tuple): w = [x.items() for x in d_tuple] first = w[0] other = w[1:] res = [] for f in first: s = 1 for elem in other: if f not in elem: s = 0 break if s: res.append(f) return dict(res) print (my_dict(*(operator_one, operator_two, operator_three))) # {5: 'try'}

Ответ 3



Ошибка в комманде for key, value in args: # перебор ключ-значение в обоих словарях так как args - кортеж из одного элемента (словаря, заданного как параметр). И так, вместо args нужно везде писать args[0] (и в цикле for добавить ещё .items()): for key, value in args[0].items(): # перебор ключ-значение в обоих словарях print("vocabulary_two:", args[0]) # вывод второго аргумента if key in args and value == args[0][key]: # если ключ-значение равно аргументу ключ-значение, то создаем новый словарь с ключом и значение Но луже вашу функцию слишком изменить - исключить параметр farg, т.к оба параметра могут быть в кортежи args: def operator_important(*args): """Перебор ключ-значения в двух словарях при помощи args и записи в новый словарь.""" operator_main = dict() # создание словаря и запись в перем print("vocabulary_one:", args[0]) # вывод первого аргумента for key, value in args[0].items(): # перебор ключ-значение в обоих словарях print("vocabulary_two:", args[1]) # вывод второго аргумента if key in args and value == args[key]: # если ключ-значение равно аргументу ключ-значение, то создаем новый словарь с ключом и значение operator_main[key] = value # добавляем в нов. словарь найденное ключ-значение, которое совпало

среда, 1 января 2020 г.

Сортировка значений словаря при помощи sorted()

#python #python_3x #сортировка #словари #dict


Задача: отсортировать значения словаря. 

Наткнулся на непонятную конструкцию: key=my_dict.get

Почему в данном случае происходит сортировка, если get-это метод класса dict и у
него есть обязательный аргумент? 
Все остальное - понятно.

result = sorted(my_dict, key=my_dict.get, reverse=True)[:3]


Спасибо за ответ.
    


Ответы

Ответ 1



Параметр key в функции sorted(iterable, /, *, key=None, reverse=False) - функция, которая вызывается для каждого элемента из iterable. Таким образом мы можем сортировать сложные объекты, указывая атрибуты или элементы вложенных списков / массивов. Пример: In [21]: my_dict = {"b": 100, "c": 10, "a": 50} In [22]: sorted(my_dict, key=my_dict.get, reverse=True) Out[22]: ['b', 'a', 'c'] можно переписать более понятным, но менее элегантным способом: In [23]: sorted(my_dict, key=lambda x: my_dict.get(x), reverse=True) Out[23]: ['b', 'a', 'c']

Ответ 2



В качестве аргумента key функции sorted передаётся имя функции, которая из сложного составляющего сортируемого возвращает значение, по которому необходимо произвести сортировку. Здесь можно прочитать подробнее. Также советую ознакомиться с официальной документацией на эту тему.

вторник, 31 декабря 2019 г.

Последовательное чтение значений из списка в словарь

#python #списки #словари


Здраствуйте. Есть готовый список, который содержит слова в определенной последовательности:
list = ['To', 'be', 'or', 'not', 'to', 'be']

Требуется подсчитать частоту появления слов в этом списке и составить словарь, который
содержит пары значений (слово) : (кол-во повторений этого слова).
Вот мой код:
# -*- coding: utf-8 -*-

list = ['To', 'be', 'or', 'not', 'to', 'be']

counts = dict()
for word in list:
    if word not in counts: # Если символа нет в словаре, создаем новую запись
        counts[word] = 1
    else: # В противном случае инкрементируем d[c]
        counts[word] += 1

print counts

Подсчет слов ведется правильно. 
Проблема в том, что моя программа помещает новые записи в словарь в хаотичном порядке,
а не так, как слова шли в предложении. Вот что интерпретатор выдает на выходе:
{'not': 1, 'To': 1, 'or': 1, 'to': 1, 'be': 2}

А должно быть так:
{'To': 1, 'be': 2, 'or': 1, 'not': 1, 'to': 1}

Как можно получить такой результат? Никак не могу монять.
P.S.: В Python я новичок, поэтому не судите строго.    


Ответы

Ответ 1



Вам нужен OrderedDict, Dict не поддерживает упорядочивание записей по умолчанию.

Ответ 2



Словарь в Питоне не обязан сохранять порядок добавления слов. Хотя некоторые реализации Питона, такие как Pypy, используют упорядоченные словари по умолчанию. Чтобы подсчитать частоту появления слов во входном списке и напечатать их в том порядке как они заданы в списке, можно объединить Counter и OrderedDict, чтобы поддерживать порядок вставки: #!/usr/bin/env python from collections import Counter, OrderedDict class OrderedCounter(Counter, OrderedDict): pass input_list = ['To', 'be', 'or', 'not', 'to', 'be'] frequencies = OrderedCounter(input_list) for item, count in frequencies.items(): print("{}\t{}".format(item, count)) Результат To 1 be 2 or 1 not 1 to 1 Если достаточно только напечатать результат, то можно обойтись только Counter, без OrderedDict или сортировки: #!/usr/bin/env python from collections import Counter input_list = ['To', 'be', 'or', 'not', 'to', 'be'] frequencies = Counter(input_list) for item in input_list: count = frequencies.pop(item, None) if count is None: continue print("{}\t{}".format(item, count)) Результат совпадает с предыдущим кодом. frequencies словарь разрушается во время печати.

Ответ 3



Вот один вариант как отсортировать: ссылка

Ответ 4



Если вам нужно просто отсортировать в алфавитном порядке, просто при выводе сделайте for key in sorted(counts.keys()): print '{0}: {1}'.format(key, counts[key]) А если именно в том порядке, в котором они встречались в первый раз - да, как писал Etki, используйте OrderedDict

понедельник, 30 декабря 2019 г.

Составной словарь в Python с несколькими значениями из других словарей по идентичному ключу

#python #словари


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

Итак, есть три разных словаря с идентичными ключами. Значения – разные, но могут
совпадать как в пределах одного словаря, так и в разных словарях.
Например (значения сделал в виде списка, поскольку понимаю, что по-другому добавлять
значения к одному ключу не выйдет):

dict_1={'a': [2],
    'b': [8],
    'c': [6],
    'd': [2]}

dict_2={'a': [2],
    'b': [7],
    'c': [7],
    'd': [3]}

dict_3={'a': [3],
    'b': [6],
    'c': [8],
    'd': [3]}


Задача: получить новый словарь (либо с нуля, либо на основе одного из указанных –
совершенно не важно) в котором каждый ключ получит значения от всех трёх словарей:

dict_all={'a': [2, 2, 3],
      'b': [8, 7, 6],
      'c': [6, 7, 8],
      'd': [2, 3, 3]}

    


Ответы

Ответ 1



Вариант решения с использованием модуля Pandas: import pandas as pd # pip install pandas res = pd.concat([pd.DataFrame(d) for d in [dict_1, dict_2, dict_3]]).to_dict('list') результат: {'a': [2, 2, 3], 'b': [8, 7, 6], 'c': [6, 7, 8], 'd': [2, 3, 3]} в виде Pandas.DataFrame: In [7]: pd.concat([pd.DataFrame(d) for d in [dict_1, dict_2, dict_3]]) Out[7]: a b c d 0 2 8 6 2 0 2 7 7 3 0 3 6 8 3

Ответ 2



import copy dict_all = copy.deepcopy(dict_1) for loop_dict in dict_2, dict_3: for k, v in loop_dict.items(): try: dict_all[k].extend(v) except KeyError: dict_all[k] = v Если сохранность в исходном виде dict_1 не нужна, можно обойтись без его глубокого копирования. Перехват ислкючения нужен на случай, если в dict_1 нет каких-либо ключей, встречающихся в других словарях.

Ответ 3



dict_all = {} for key in dict_1: dict_all[key] = [d[key][0] for d in (dict_1, dict_2, dict_3)] Примечание: Исходные словари не нужны иметь в качестве значений списки - в том случае просто удалите в моем решении [0] (служащего для выбора первого - единого - элемента исходных списков).

Ответ 4



Оптимально не привязывать необходимый набор ключей к какому-либо "рабочему" словарю, в следующей функции набор ключей вынесен в качестве параметра. В ваших словарях значения представлены списками с одним элементом, удобно привести их к общему базовому виду с помощью отдельной функции-фильтра def general_dict(key_list, ad, bd, cd): result = {} for key in key_list: t = [] for d in [ad, bd, cd]: try: t.append(d[key]) except KeyError: pass result[key] = t return result def dict_filter(dict): y = {} for x in dict: y[x] = dict[x][0] return y dict_1={'a': [2], 'b': [8], 'c': [6], 'd': [2]} dict_2={'a': [2], 'b': [7], 'c': [7], 'd': [3]} dict_3={'a': [3], 'b': [6], 'c': [8], 'd': [3]} print dict_filter(dict_1) # {'a': 2, 'c': 6, 'b': 8, 'd': 2} print general_dict(['a', 'b', 'c', 'd'], dict_filter(dict_1), dict_filter(dict_2), dict_filter(dict_3)) # {'a': [2, 2, 3], 'c': [6, 7, 8], 'b': [8, 7, 6], 'd': [2, 3, 3]}