How do i swap my keys and values without it reading letter for letter?

61 Views Asked by At

I have to read a text file and make it a dictionary, then swap those keys and values and write it back to a new file, I cannot import anything either, the issue I'm having is right now I end up with it turning my values into letter by letter instead of words.

my text file is this:

Cloth:Stitching
Leather:Stitching,
Blacksmith:Molding
Pottery:Shaping
Metalworking:Molding
Baking:Heating

This has been a struggle because I do not know why, but lists, dictionaries and tuples are something my head is not wrapping around.

I tried to write my code in 2 ways

1st:

with open('trial.txt', 'r') as f:
    fr = f.readlines()
    prof = {}
    for line in fr:
        key , value=line.strip().split(":")
        prof[key]=value
        profr = {}
        for key, values in prof.items():
            for value in values:
                if value in profr:
                    profr[value].append(key)
                else:
                    profr[value]=[key]

output:

{',': ['Leather'],
 'H': ['Baking'],
 'M': ['Blacksmith', 'Metalworking'],
 'S': ['Cloth', 'Leather', 'Pottery'],
 'a': ['Pottery', 'Baking'],
 'c': ['Cloth', 'Leather'],
 'd': ['Blacksmith', 'Metalworking'],
 'e': ['Baking'],
 'g': ['Cloth', 'Leather', 'Blacksmith', 'Pottery', 'Metalworking', 'Baking'],
 'h': ['Cloth', 'Leather', 'Pottery'],
 'i': ['Cloth',
       'Cloth',
       'Leather',
       'Leather',
       'Blacksmith',
       'Pottery',
       'Metalworking',
       'Baking'],
 'l': ['Blacksmith', 'Metalworking'],
 'n': ['Cloth', 'Leather', 'Blacksmith', 'Pottery', 'Metalworking', 'Baking'],
 'o': ['Blacksmith', 'Metalworking'],
 'p': ['Pottery'],
 't': ['Cloth', 'Cloth', 'Leather', 'Leather', 'Baking']}

2nd try which just removes .items() to resemble my old code that worked however that code did not read a text file:

with open('trial.txt', 'r') as f:
    fr = f.readlines()
    prof = {}
    for line in fr:
        key , value=line.strip().split(":")
        prof[key]=value
        profr = {}
        for key, values in prof:
            for value in values:
                if value in profr:
                    profr[value].append(key)
                else:
                    profr[value]=[key]

output:

*** Remote Interpreter Reinitialized ***
Traceback (most recent call last):
  File "D:\code\Scripts\Menu.py", line 8, in <module>
    for key, values in prof:
        ^^^^^^^^^^^
ValueError: too many values to unpack (expected 2)

What do I need to do to get the desired output of:

Stitching: Cloth, Leather
Molding: Blacksmith, Metalworking
Shaping:Pottery
Heating:Baking

An explanation or links to an explanation would be helpful. I have googled a lot though so I do not know if anyone would link something I have not seen yet.

2

There are 2 best solutions below

4
James On BEST ANSWER

Normally, you could parse it directly to a defaultdict with list as the default value factory.

from collections import defaultdict

profr = defaultdict(list)
with open('trial.txt', 'r') as f:
    for line in f:
        v, k = line.strip(', \n').split(':')
        profr[k].append(v)

The defaultdict(list) object behaves just like a dictionary, with the exception of when a new key is pass, it creates an empty list instead of raising a KeyError.


However, since you said you cannot import anything, you can replicate this behavior with the regular dictionary using the setdefault method:

profr = {}

with open('trial.txt', 'r') as f:
    for line in f:
        v, k = line.strip(', \n').split(':')
        profr.setdefault(k, []).append(v)

with open('out.txt', 'w') as fp:
    for k, v_list in profr.items():
        v_str = ', '.join(v_list)
        fp.write(f'{k}:{v_str}\n')

The setdefault(key, value) method of a dictionary does the following:

  • if key exists in the dictionary, it returns existing value
  • if key does not exist, it adds key, sets the value to value and returns value.

So in your case, if the key does not exist, a new empty list is assigned to the value for that key; and the empty list is returned, allowing us to call .append.

But if the key already exists - in this case, with a list as the value - then the list is returned, also allowing us to call .append.

As your code reads each line of text, you can parse it directly to what you need. In this case, since you are swapping the keys and values, then you can simply parse each line as a value:key pair, instead of the other way. That is what this line is doing:

v, k = line.strip(', \n').split(':')

The value comes first, and the key second. It is also cleaning up any extra whitespace and commas.

1
Eugene Vdovichenko On

At least for the second error you need to write for key, values in prof.items():