1

I have a file with the first two lines looking like this:

(1,233)(44,444)(2323,545)(0,0)(22,2)(5,0)(222,2)(0,5)(12,2)(22,3)
(0,223)(44,424)(123,545)(0,1)(42,2)(5,0)(52,2)(0,6)(17,4)(3,3)

I want to read each tuple and get each number (without the commas and parenthesis). I read like this:

file = filedialog.askopenfilename(filetypes=[("Text files","*.txt")])
if file is None:
    return False

with open(file, 'r') as f:
    lines = f.read().split("\n")
    firstLine = lines[0]
    secondLine = lines[1]

    # Run loop here to get the tuple values
    # firstNum = tuple[0]
    # secondNum = tuple[1]

    # Go to next line and do the same

How can I go about doing the above? Any help would be appreciated.

martineau
  • 119,623
  • 25
  • 170
  • 301
cress
  • 389
  • 3
  • 13
  • 1
    To be clear, do you want to get the numbers in one flat list like so: 1, 233, 44, 444, 2323, 545, etc, or do you still want them in pairs, e.g., (1, 233), (44, 444), etc? – Reti43 Feb 05 '17 at 23:27
  • Whichever one would be easier so I can just do `firstNum = first number in tuple, secondNum = second number in tuple`. I'm assuming saving them in pairs would be better as I can just reference them by their index: `[0]` and `[1]`. – cress Feb 05 '17 at 23:29

5 Answers5

2

I would go for regular expressions:

[(int(x), int(y)) for x,y in re.findall(r"\((\d+),\s*(\d+)\)", line)]
# [(1, 233), (44, 444), (2323, 545), (0, 0), (22, 2), (5, 0), (222, 2), ...]

Another interesting solution is to convert the line into a valid Python tuple by inserting commas between the pairs and then apply ast.litereal_eval:

list(ast.literal_eval(line.replace(")", "),")))
# [(1, 233), (44, 444), (2323, 545), (0, 0), (22, 2), (5, 0), (222, 2), ...]
DYZ
  • 55,249
  • 10
  • 64
  • 93
2

Here's a relatively simple way of doing it that uses ast.literal_eval():

import ast

with open('tuple.txt') as file:
    for line in file:
        numbers = ast.literal_eval(line.replace(')(', '),('))
        print('numbers: {}'.format(numbers))
        for _1st_num, _2nd_num in numbers:
            print(_1st_num, _2nd_num)

Output:

numbers: ((1, 233), (44, 444), (2323, 545), (0, 0), (22, 2), (5, 0), (222, 2), (0, 5), (12, 2), (22, 3))
1 233
44 444
2323 545
0 0
22 2
5 0
222 2
0 5
12 2
22 3
numbers: ((0, 223), (44, 424), (123, 545), (0, 1), (42, 2), (5, 0), (52, 2), (0, 6), (17, 4), (3, 3))
0 223
44 424
123 545
0 1
42 2
5 0
52 2
0 6
17 4
3 3
martineau
  • 119,623
  • 25
  • 170
  • 301
  • Nice. You just taught me `literal_eval()`. – Reti43 Feb 06 '17 at 00:05
  • @Reti43: Thanks.`ast.literal_eval()` is a safe alternative to the built-in [`eval()`](https://docs.python.org/3/library/functions.html#eval) function because it only works for strings containing expressions referencing literal values. Also note my updated answer in which I've simplified the processing even more. – martineau Feb 06 '17 at 03:57
1

First way

Replace all brackets and commas with spaces and then split the line removing the spaces. Thus, you obtain a flat list of all the numbers. By iterating through the list and getting the numbers at indices i and i+1, you can get them in pairs.

>>> line = "(1,233)(44,444)(2323,545)(0,0)(22,2)(5,0)(222,2)(0,5)(12,2)(22,3)"
>>> line_edited = line.replace("(", " ").replace(")", " ").replace(",", " ").split()
>>> line_edited
['1', '233', '44', '444', '2323', '545', '0', '0', '22', '2', '5', '0', '222', '2', '0', '5', '12', '2', '22', '3']
>>> for i in xrange(0, len(line_edited), 2):
    print line_edited[i], line_edited[i+1]


1 233
44 444
2323 545
0 0
22 2
5 0
222 2
0 5
12 2
22 3

Second way

Similar to the first way, except that you only replace the brackets with spaces and split. Now, you get a list of strings "first_number,second_number", so you iterate through those and split at the comma to get the pair.

>>> line_edited = line.replace("(", " ").replace(")", " ").split()
>>> line_edited
['1,233', '44,444', '2323,545', '0,0', '22,2', '5,0', '222,2', '0,5', '12,2', '22,3']
>>> for pair in line_edited:
    first_number, second_number = pair.split(",")
    print first_number, second_number


1 233
44 444
2323 545
0 0
22 2
5 0
222 2
0 5
12 2
22 3

You can read more about replacing multiple characters in a string here.

Community
  • 1
  • 1
Reti43
  • 9,656
  • 3
  • 28
  • 44
1

You can, also, do it like this example (i assume your input file is called input_file):

data = (k.rstrip().replace("(", "").replace(")", " ").strip().split(" ") for k in open("input_file", 'r'))

for k in data:
    for j in (i.split(',') for i in k):
        print("{} {}".format(j[0], j[1]))

Output:

1 233
44 444
2323 545
0 0
22 2
5 0
222 2
0 5
12 2
22 3
0 223
44 424
123 545
0 1
42 2
5 0
52 2
0 6
17 4
3 3
Chiheb Nexus
  • 9,104
  • 4
  • 30
  • 43
0

This will do it - if you can hold your gag reflex long enough:

with open(file, 'r') as f:
    lines = f.read().split("\n")
    for line in lines:
      input=[scanf("%d,%d)",a) for a in line[1:].split('(')]
      # process each tuple in 'input' before continuing with next line

Maybe just go with DYZs answer.

Amorpheuses
  • 1,403
  • 1
  • 9
  • 13