3

This is my python file:-

TestCases-2
Input-5
Output-1,1,2,3,5
Input-7
Ouput-1,1,2,3,5,8,13

What I want is this:-

  • A variable test_no = 2 (No. of testcases)
  • A list testCaseInput = [5,7]
  • A list testCaseOutput = [[1,1,2,3,5],[1,1,2,3,5,8,13]]

I've tried doing it in this way:

               testInput = testCase.readline(-10)

        for i in range(0,int(testInput)):
            testCaseInput = testCase.readline(-6)
            testCaseOutput = testCase.readline(-7)

The next step would be to strip the numbers on the basis of (','), and then put them in a list.

Weirdly, the readline(-6) is not giving desired results.

Is there a better way to do this, which obviously I'm missing out on.

I don't mind using serialization here but I want to make it very simple for someone to write a text file as the one I have shown and then take the data out of it. How to do that?

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
Hick
  • 35,524
  • 46
  • 151
  • 243
  • 1
    What results are you expecting, and what exactly do you think a negative parameter to the .`readline()` method is supposed to do? – Wooble Oct 24 '11 at 11:16
  • What I expected readline(-6) it to do, or it was doing rather, was to jump to the 6th character of the line and then store it from there till the end of the line with a '\n' at the end. – Hick Oct 24 '11 at 11:20

4 Answers4

2

I'm not sure if I follow exactly what you're trying to do, but I guess I'd try something like this:

testCaseIn = [];
testCaseOut = [];

for line in testInput:
    if (line.startsWith("Input")):
        testCaseIn.append(giveMeAList(line.split("-")[1]));
    elif (line.startsWith("Output")):
        testCaseOut.append(giveMeAList(line.split("-")[1]));

where giveMeAList() is a function that takes a comma seperated list of numbers, and generates a list datathing from it.

I didn't test this code, but I've written stuff that uses this kind of structure when I've wanted to make configuration files in the past.

Oliver
  • 11,297
  • 18
  • 71
  • 121
  • This is exactly what I've written in a better way, of course. Thank you. Will Pickle make my work easier? – Hick Oct 24 '11 at 11:31
  • 1
    I've never used it. Pickle always struck me as something for turning python objects into files, and then later turning them back into objects, rather than something for letting a user write config stuff, and then turn that into a object. If you're making production code you might need something more robust, but if you're just hacking something together I think a simple configuration system like this is good enough. If you want to be more verbose, you could throw something together with XML. – Oliver Oct 24 '11 at 11:55
  • I like the simplicity of this variant. – Raymond Hettinger Oct 25 '11 at 04:51
2

A negative argument to the readline method specifies the number of bytes to read. I don't think this is what you want to be doing.

Instead, it is simpler to pull everything into a list all at once with readlines():

with open('data.txt') as f:
    full_lines = f.readlines()

# parse full lines to get the text to right of "-"
lines = [line.partition('-')[2].rstrip() for line in full_lines]

numcases = int(lines[0])
for i in range(1, len(lines), 2):
    caseinput = lines[i]
    caseoutput = lines[i+1]
    ...

The idea here is to separate concerns (the source of the data, the parsing of '-', and the business logic of what to do with the cases). That is better than having a readline() and redundant parsing logic at every step.

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
1
  1. This line has an error:

    Ouput-1,1,2,3,5,8,13  // it should be 'Output' not 'Ouput
    
  2. This should work:

    testCase = open('in.txt', 'r')
    testInput = int(testCase.readline().replace("TestCases-",""))
    for i in range(0,int(testInput)):
        testCaseInput = testCase.readline().replace("Input-","")
        testCaseOutput = testCase.readline().replace("Output-","").split(",")
    
DhruvPathak
  • 42,059
  • 16
  • 116
  • 175
  • This would store both the test-cases or rather any number of test-cases. Thank you. But, would pickle make my work easier? – Hick Oct 24 '11 at 11:32
  • 1
    @Hiccup If that file you are reading is an output from your python program then yes, pickle.dump() and pickle.load() would be easier. – rplnt Oct 24 '11 at 11:40
1

You can use regex for this and it makes it much easier. See question: python: multiline regular expression

For your case, try this:

import re
s = open("input.txt","r").read()
(inputs,outputs) = zip(*re.findall(r"Input-(?P<input>.*)\nOutput-(?P<output>.*)\n",s))

and then split(",") each output element as required

If you do it this way you get the benefit that you don't need the first line in your input file so you don't need to specify how many entries you have in advance.

You can also take away the unzip (that's the zip(*...) ) from the code above, and then you can deal with each input and output a pair at a time. My guess is that is in fact exactly what you are trying to do.

EDIT Wanted to give you the full example of what I meant just then. I'm assuming this is for a testing script so I would say use the power of the pattern matching iterator to help keep your code shorter and simpler:

for (input,output) in re.findall(r"Input-(?P<input>.*)\nOutput-(?P<output>.*)\n",s):
  expectedResults = output.split(",")

  testResults = runTest(input)
  // compare testResults and expectedResults ...
Community
  • 1
  • 1
Benedict
  • 2,771
  • 20
  • 21
  • If you're comfortable with regular expressions, this is a very clean approach. It expresses the business logic well. Also it does a good job of separating reading from parsing from working with the results. This makes the code more maintainable (if you're comfortable with regular expressions). – Raymond Hettinger Oct 25 '11 at 00:32
  • Thanks for the positive comments. Why should this approach be dependent on being comfortable with regular expressions? If you are uncomfortable with them, it is a relatively gentle introduction to their power. – Benedict Oct 25 '11 at 15:55