MaxPower
MaxPower

Reputation: 425

Group values under certain key

My code so far:

from collections import OrderedDict as od
    def load(fileIn, fileOut):
        with open(fileIn+'.txt') as fin, open(fileOut+'.txt', 'w') as fout:
            dict = od()
            for line in fin:
                row = line.split()
                id = int(row[0])
                frame = int(row[2])
                rect = [int(row[3]),int(row[4]),int(row[5]),int(row[6])]
                dict = {frame:[id, rect]}
                fout.writelines(str(dict)+'\n')

reads from a text file, sorts it in a specific way and writes it to a new one. I need to add another for loop or possibly two more so i can sort it better before i write it and this is where i am struggling.

Here are the input and output examples to make things more clear:

Input:

2 109 1 561 1 20 28 1
2 109 2 557 1 24 32 1
2 109 3 557 5 24 32 1
2 109 4 553 5 28 32 1
2 109 5 553 1 36 40 1
239 195 1 101 549 40 28 1
239 195 2 100 549 40 28 1
239 195 3 98 549 40 28 1
239 195 4 91 551 40 28 1
239 195 5 93 549 40 28 1

Output:

 {1: [2, [561, 1, 20, 28]]}
{2: [2, [557, 1, 24, 32]]}
{3: [2, [557, 5, 24, 32]]}
{4: [2, [553, 5, 28, 32]]}
{5: [2, [553, 1, 36, 40]]}
{1: [239, [101, 549, 40, 28]]}
{2: [239, [100, 549, 40, 28]]}
{3: [239, [98, 549, 40, 28]]}
{4: [239, [91, 551, 40, 28]]}
{5: [239, [93, 549, 40, 28]]}

I am trying to group all of the values of the different rects under one key which is the common frame they all share. So if frame 1 appears 100 times in a file under different id every time, i need all of the rects under one key which will have 100 different rects in it.

So an example of that would be:

{1:[rect],[rect],[rect],[rect],[rect],[rect],[rect],[rect],[rect]}
{2:[rect],[rect],[rect],[rect],[rect],[rect],[rect],[rect],[rect]}
{3:[rect],[rect],[rect],[rect],[rect],[rect],[rect],[rect],[rect]}

Then i can compare frame 1 in one file to frame 1 in another file.

Upvotes: 1

Views: 86

Answers (2)

martineau
martineau

Reputation: 123463

This does it in two steps and sorts the intermediate output into the desired order. Note that theidof each rectangle is ignored since it's not in the final output shown in your question.

from collections import defaultdict

def load(fileIn, fileOut):
    with open(fileIn+'.txt') as fin:
        frame_rects = defaultdict(list)

        for row in (map(int, line.split()) for line in fin):
            frame, rect = row[2], [row[3],row[4],row[5],row[6]]
            frame_rects[frame].append(rect)
        fin.close()
        with open(fileOut+'.txt', 'w') as fout:
            for frame, rects in sorted(frame_rects.iteritems()):
                fout.write('{{{}:{}}}\n'.format(frame, rects))

load('filein', 'fileout')

Output:

{1:[[561, 1, 20, 28], [101, 549, 40, 28]]}
{2:[[557, 1, 24, 32], [100, 549, 40, 28]]}
{3:[[557, 5, 24, 32], [98, 549, 40, 28]]}
{4:[[553, 5, 28, 32], [91, 551, 40, 28]]}
{5:[[553, 1, 36, 40], [93, 549, 40, 28]]}

Upvotes: 2

Johannes Jasper
Johannes Jasper

Reputation: 921

The way you are using the dictionary seems not quite right to me.

dict = {frame:[id, rect]}
fout.writelines(str(dict)+'\n')

These lines overwrite your dict in every loop, so you have a dict with only one key : value pair. Then you write this straight to you output file. There is no sorting or grouping at all.

What you want (if I understood you correctly) is one big dictionary, with frame as key and a list of rects as value. Something like:

frame | rects
  1   | [rect1, rect2]
  2   | [rect3, rect4, rect5]

Then you should create one dict. In the loop you should get the value mapped to your frame (dict[frame]). If there is no such key yet, create a new list with your rect as first element. If there already is a list mapped to the frame, you should append your rect to it.

In the end you can iterate over your dict and write it to your output file.

I hope I understood you correctly and this helps.

Upvotes: 2

Related Questions