Как получить доступ к ключам в словаре? - PullRequest
0 голосов
/ 05 июля 2019

Будучи новичком в python, я работал с CSV-файлом и создал список ребер так, чтобы значения имели однозначное соответствие со значениями этой строки в CSV, например: Выход:

value1 value2     
value1 value3
value2 value3    
value4 value5
.
.
.

Затем я присвоил уникальные номера каждому из этих значений в файле CSV, так что уникальный номер действует как ключ, а элемент в CSV действует как значение, как в словаре. Также, если какое-либо значение повторяется в файле CSV, я не хочу назначать ему другой ключ.

Выход:

dictionary=
{
1: "value1",
2: "value2",
3: "value3",
.
.
.
}

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

1 2
1 3
2 3
.
.
.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 06 июля 2019

Не следует вручную управлять индексами в циклах (while(j!=len(i)-1)), если у вас нет выбора.

Для комбинаций вы можете использовать itertools:

>>> import itertools
>>> list(itertools.combinations(["man", "nut", "bag"], 2))
[('man', 'nut'), ('man', 'bag'), ('nut', 'bag')]

Тогда легко получить края.

Я создаю ридер для приведенного вами примера:

>>> data = """man,nut,bag
... rat,cat
... dog,fog,cat,man"""
...
>>> import io
>>> import csv
>>> reader = csv.reader(io.StringIO(data))

Ребра являются объединением комбинаций для каждой строки:

>>> edges = [(v1, v2) for row in reader for v1, v2 in itertools.combinations(row, 2)]
>>> edges
[('man', 'nut'), ('man', 'bag'), ('nut', 'bag'), ('rat', 'cat'), ('dog', 'fog'), ('dog', 'cat'), ('dog', 'man'), ('fog', 'cat'), ('fog', 'man'), ('cat', 'man')]

Теперь вы можете извлекать уникальные элементы из edges:

>>> vs = sorted(set(a for e in edges for a in e))
>>> vs
['bag', 'cat', 'dog', 'fog', 'man', 'nut', 'rat']

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

>>> list(enumerate(vs))
[(0, 'bag'), (1, 'cat'), (2, 'dog'), (3, 'fog'), (4, 'man'), (5, 'nut'), (6, 'rat')]
>>> i_by_v = {v: i for i, v in enumerate(vs)}
>>> i_by_v
{'bag': 0, 'cat': 1, 'dog': 2, 'fog': 3, 'man': 4, 'nut': 5, 'rat': 6}

Заменим вершины на их количество:

>>> [(i_by_v[v1], i_by_v[v2]) for v1, v2 in edges]
[(4, 5), (4, 0), (5, 0), (6, 1), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4), (1, 4)]

Теперь вы можете использовать любой алгоритм на графике.

0 голосов
/ 05 июля 2019

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

Найдите ниже мой предложенный код:

#!/usr/bin/python                                                                                                   

# -*- coding: utf-8 -*-

# For better print formatting
from __future__ import print_function

# Imports
import sys


#
# HELPER METHODS
#

def mapping(csv_filename, mapping_filename):
    if __debug__:
        print("CSV File: " + str(csv_filename))
        print("Mapping File: " + str(mapping_filename))

    # Retrieve data from CSV file
    with open(csv_filename, "r") as csv_file:
        data_raw = csv_file.readlines()
    data = []
    for line in data_raw:
        line = line.strip()
        elements = line.split(",")
        elements = [e.strip() for e in elements]
        data.append(elements)

    # Create mapping list and file
    mapping_list = []
    with open(mapping_filename, "w") as mapping_file:
        for elements in data:
            j = 0
            while j != len(elements) - 1:
                for k in range(j + 1, len(elements)):
                    # Add to mapping
                    temp = [elements[j], elements[k]]
                    mapping_list.append(temp)
                    # Write to file
                    mapping_file.write(elements[j] + " " + elements[k] + "\n")
                j += 1

    # Return the mapping
    return mapping_list


def build_key_map(mapping_list):
    if __debug__:
        print("Mapping List: " + str(mapping_list))

    key_dict = {}
    i = 1
    # Check each parsed node inside each edge
    for edge in mapping_list:
        for node in edge:
            # Add node to keys if it has not been registered yet
            if node not in key_dict.keys():
                key_dict[node] = i
                i = i + 1

    return key_dict


def build_graph(mapping_list, key_dict):
    if __debug__:
        print("Mapping List: " + str(mapping_list))
        print("Key Dict: " + str(key_dict))

    # Copy the existing mapping changing each node (inside edge) by its unique number
    new_mapping_list = []
    for edge in mapping_list:
        new_edge = []
        for node in edge:
            new_edge.append(key_dict[node])
        new_mapping_list.append(new_edge)

    return new_mapping_list


#
# MAIN
#

def main():
    import sys
    csv_file = sys.argv[1]
    mapping_file = sys.argv[2]

    mapping_list = mapping(csv_file, mapping_file)
    key_dict = build_key_map(mapping_list)
    new_mapping_list = build_graph(mapping_list, key_dict)

    print("FINAL MAPPING: ")
    for edge in new_mapping_list:
        print(edge)


#
# ENTRY POINT
#

if __name__ == "__main__":
    main()

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

  • mapping function анализирует файл CSV и создает карту (список ребер от узла к узлу) и записывает ее в заданный файл. Здесь синтаксический анализ CSV разделяется на «,» (как пример, который вы предоставили), хотя ваш исходный код разделял его на «:».
  • build_key_map создает словарь из имен узлов в уникальные числа.
  • build_graph преобразует сопоставление с именами узлов, используя их уникальный номер.

Используя ваш ввод, ожидаемый вывод:

> python parser.py "csv.txt" "map.txt"
CSV File: csv.txt
Mapping File: map.txt
Mapping List: [['man', 'nut'], ['man', 'bag'], ['nut', 'bag'], ['rat', 'cat'], ['dog', 'fog'], ['dog', 'cat'], ['dog', 'man'], ['fog', 'cat'], ['fog', 'man'], ['cat', 'man']]
Mapping List: [['man', 'nut'], ['man', 'bag'], ['nut', 'bag'], ['rat', 'cat'], ['dog', 'fog'], ['dog', 'cat'], ['dog', 'man'], ['fog', 'cat'], ['fog', 'man'], ['cat', 'man']]
Key Dict: {'nut': 2, 'dog': 6, 'cat': 5, 'bag': 3, 'rat': 4, 'fog': 7, 'man': 1}
FINAL MAPPING: 
[1, 2]
[1, 3]
[2, 3]
[4, 5]
[6, 7]
[6, 5]
[6, 1]
[7, 5]
[7, 1]
[5, 1]

Кроме того, я добавил несколько комментариев, но сообщите мне, если мне нужно уточнить какую-то часть.

EDIT:

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

inverted_dict = dict([[v,k] for k,v in key_dict.items()])

EDIT2:

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

def mapping(csv_filename, mapping_filename):
    if __debug__:
        print("CSV File: " + str(csv_filename))
        print("Mapping File: " + str(mapping_filename))

    # Retrieve data from CSV file
    with open(csv_filename, "r") as csv_file:
        data_raw = csv_file.readlines()
    data = []
    for line in data_raw:
        line = line.strip()
        elements = line.split(",")
        elements = [e.strip() for e in elements]
        data.append(elements)

    # Create mapping list and file
    mapping_list = []
    key_dict = {}
    unique_num = 1
    with open(mapping_filename, "w") as mapping_file:
        for elements in data:
            j = 0
            while j != len(elements) - 1:
                for k in range(j + 1, len(elements)):
                    if __debug__:
                        print("Converting: " + elements[j] + " -> " + elements[k])
                    # Transform elements to keys
                    if elements[j] in key_dict.keys():
                        key_j = key_dict[elements[j]]
                    else:
                        key_dict[elements[j]] = unique_num
                        key_j = unique_num
                        unique_num = unique_num + 1
                    if elements[k] in key_dict.keys():
                        key_k = key_dict[elements[k]]
                    else:
                        key_dict[elements[k]] = unique_num
                        key_k = unique_num
                        unique_num = unique_num + 1
                    # Add to mapping
                    if __debug__:
                        print("Adding: " + str(key_j) + " -> " + str(key_k))
                    mapping_list.append([key_j, key_k])
                    # Write to file
                    mapping_file.write(str(key_j) + " " + str(key_k) + "\n")
                j += 1

    # Return the mapping
    return mapping_list

Ожидаемый результат:

> python parser.py "csv.txt" "map.txt"
CSV File: csv.txt
Mapping File: map.txt
Converting: man -> nut
Adding: 1 -> 2
Converting: man -> bag
Adding: 1 -> 3
Converting: nut -> bag
Adding: 2 -> 3
Converting: rat -> cat
Adding: 4 -> 5
Converting: dog -> fog
Adding: 6 -> 7
Converting: dog -> cat
Adding: 6 -> 5
Converting: dog -> man
Adding: 6 -> 1
Converting: fog -> cat
Adding: 7 -> 5
Converting: fog -> man
Adding: 7 -> 1
Converting: cat -> man
Adding: 5 -> 1
FINAL MAPPING: 
[1, 2]
[1, 3]
[2, 3]
[4, 5]
[6, 7]
[6, 5]
[6, 1]
[7, 5]
[7, 1]
[5, 1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...