Forest
Forest

Reputation: 13

Python read items from a file into a dictionary

I'm trying to read values from a file and get them into a dictionary as lists so I can later use them in functions, for example get the sum of Maths KT and get the length of the list and check if contains atleast 5 values and so on.

The code I have for getting the file into a dictionary.

    s = {}
f = open("file.txt")
lines = f.readlines()

for i in lines:
    if not ":" in i:
        if i.strip() == "":
            pass
        else:
            s[i.strip()] = {}
    elif ":" in i:
        x = i.strip().split(":")
        s[next(iter(s))][x[0]] = x[1].split(",")

print(s)
f.close()

It currently prints it out like this:

 {'Maths': {'TK': [' 1', ' 2', ' 2', ' 2', ' 0.5'], 'KT': [' 25', ' 10'], 'Tests': [' 10', ' 7'], 'KD': [' 10', ' 15', ' 25']}, 'Physics': {}}

It replaces Maths values with Physics values and just adds unique Physics values to Maths, leaving Physics dictionary empty.

But it needs to look like this so I can use the keys and values:

{'Maths': {'TK': [' 1', ' 2', ' 2', ' 2', ' 0.5'], 'KT': [' 26', ' 24', ' 20'], 'Tests': [' 2 ', '2', ' 2', ' 2', ' 1'], 'KD': [' 5', ' 1']}, 'Physics': {'KD': [' 10', ' 15', ' 25'], 'KT': [' 25', ' 10'], 'Tests': [' 10', ' 7']}

How the file "file.txt" looks like (It will have more lines and values):

Maths

TK: 1, 2, 2, 2, 0.5
KT: 26, 24, 20
Tests: 2 ,2, 2, 2, 1
KD: 5, 1

Physics

KD: 10, 15, 25
KT: 25, 10
Tests: 10, 7

Upvotes: 1

Views: 86

Answers (2)

wwii
wwii

Reputation: 23783

Iterate over the file; skip blank/empty lines; split each line on ':'; if there wasn't a colon it must be a new topic - create a new dictionary; if there was a colon add to the current dictionary.

data = {}
for line in f:
    if len(line) == 1:
        continue
    line = line.strip()
    k,*v = line.split(':')
    if not v:
        d = {}
        data[k] = d
    else:
        d[k] = v[0].split(',')

Takes advantage of extended unpacking
Assumes that a topic isn't repeated later in the file - there is only one Maths section in the file.

Upvotes: 2

r.ook
r.ook

Reputation: 13898

Assuming your file looks like this in actuality:

Maths

TK: 1, 2, 2, 2, 0.5
KT: 26, 24, 20
Tests: 2 ,2, 2, 2, 1
KD: 5, 1

Physics

KD: 10, 15, 25
KT: 25, 10
Tests: 10, 7

You just need a minor modification to cache your main dictionary key. I've updated your code to also use a with context manager as well, which you should get into the practice of using:

s = {}
key = ''                                    # add a tracer for the main dictionary key
with open("test.txt", 'r') as f:
    lines = f.readlines()

    for i in lines:
        if not ":" in i:
            if i.strip() == "":
                pass
            else:
                key = i.strip()             # cache the category as key            
                s[key] = {}                 # create the main key
        else:                               # you just need an else here since the condition are polar opposites.
            x = i.strip().split(":")
            s[key][x[0]] = x[1].split(",")  # use key here instead of next(iter(s))

    print(s)

Output:

{
  'Maths': 
    {
      'TK':    [' 1', ' 2', ' 2', ' 2', ' 0.5'], 
      'KT':    [' 26', ' 24', ' 20'], 
      'Tests': [' 2 ', '2', ' 2', ' 2', ' 1'], 
      'KD':    [' 5', ' 1']
    },
  'Physics': 
    {
      'KD':    [' 10', ' 15', ' 25'],
      'KT':    [' 25', ' 10'],
      'Tests': [' 10', ' 7']
    }
}

The reason why your code didn't work was that next(iter(s)) creates a new iterator for s each time and therefore is not consistent behaviour.

Upvotes: 1

Related Questions