Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create Python dictionary with multiple 'lists' for each key by reading from .txt file?

I have a large text file that looks like:

1   27  21  22
1   151 24  26
1   48  24  31
2   14  6   8
2   98  13  16
.
.
.

that I want to create a dictionary with. The first number of each list should be the key in the dictionary and should be in this format:

{1: [(27,21,22),(151,24,26),(48,24,31)],
 2: [(14,6,8),(98,13,16)]}

I have the following code (with total points being the largest number in the first column of the text file (ie largest key in dictionary)):

from collections import defaultdict

info = defaultdict(list)
filetxt = 'file.txt'
i = 1

with open(filetxt, 'r') as file:
    for i in range(1, num_cities + 1):
        info[i] = 0
    for line in file:
        splitLine = line.split()
        if info[int(splitLine[0])] == 0:
            info[int(splitLine[0])] = ([",".join(splitLine[1:])])
        else:
            info[int(splitLine[0])].append((",".join(splitLine[1:])))

which outputs

{1: ['27,21,22','151,24,26','48,24,31'],
 2: ['14,6,8','98,13,16']}

The reason I want to do this dictionary is because I want to run a for loop through each "inner list" of the dictionary for a given key:

for first, second, third, in dictionary:
   ....

I cannot do this with my current code because of the slightly different format of the dictionary (it expects 3 values in the for loop above, but receives more than 3), however it would work with the first dictionary format.

Can anyone suggest anyway to fix this?

like image 405
aboublemc Avatar asked Jan 05 '23 07:01

aboublemc


2 Answers

result = {}
with open(filetxt, 'r') as f:
    for line in f:
        # split the read line based on whitespace
        idx, c1, c2, c3 = line.split()

        # setdefault will set default value, if the key doesn't exist and
        # return the value corresponding to the key. In this case, it returns a list and
        # you append all the three values as a tuple to it
        result.setdefault(idx, []).append((int(c1), int(c2), int(c3)))

Edit: Since you want to the key also to be an integer, you can map the int function over the split values, like this

        idx, c1, c2, c3 = map(int, line.split())
        result.setdefault(idx, []).append((c1, c2, c3))
like image 89
thefourtheye Avatar answered Jan 13 '23 14:01

thefourtheye


You are converting your values back to comma separated strings, which you can't use in for first, second, third in data - so just leave them as a list splitLine[1:] (or convert to tuple).
You don't need your initializing for loop with a defaultdict. You also don't need the conditional checks with defaultdict either.

Your code without the superfluous code:

with open(filetxt, 'r') as file:
    for line in file:
       splitLine = line.split()
       info[int(splitLine[0])].append(splitLine[1:])

One slight difference is if you want to operate on ints I would convert up front:

with open(filetxt, 'r') as file:
    for line in file:
       splitLine = list(map(int, line.split()))   # list wrapper for Py3
       info[splitLine[0]].append(splitLine[1:])

Actually in Py3, I would do:

       idx, *cs = map(int, line.split())
       info[idx].append(cs)
like image 22
AChampion Avatar answered Jan 13 '23 14:01

AChampion