0

Ok so I made a method in python that does exactly what I want it to but its really ugly and repetitive, all it needs to do is get the first 4 integers in a string of input and return them in the form ((int1, int2), (int3, int4)). There has got to be a better way of doing this (maybe even in one line) using list comprehension or something of that sort. Any ideas??

def getMove(playerInput) :
nextNum = 0
x1 = 0
y1 = 0
x2 = 0
y2 = 0
for c in playerInput:
    try:
        if nextNum==0 :
            x1 = int(c)
            nextNum += 1
        elif nextNum==1 :
            y1 = int(c)
            nextNum += 1
        elif nextNum==2 :
            x2 = int(c)
            nextNum += 1
        elif nextNum==3 :
            y2 = int(c)
            nextNum += 1
        else :
            return ((x1,y1),(x2,y2))
    except ValueError:
        break

return ((x1,y1), (x2,y2))

Thanks in advance for your helpful comments.

4
  • 1
    Example: If my playerInput = "(1,1) (1,2)" I would then like to return just the integers in the form ((1,1),(1,2)). Commented Nov 4, 2011 at 23:03
  • 1
    Wouldn't your code fail too in this situation? Commented Nov 4, 2011 at 23:05
  • 1
    With that example, your code doesn't work. That's it for "does exactly what I want it to." Commented Nov 4, 2011 at 23:10
  • Opps, I just realized I had "pass" (in my code) instead of the "break"(above), it is supposed to skip it if its not an int. Commented Nov 4, 2011 at 23:18

3 Answers 3

2

Here is what you want, using a regular expression and a simple list comprehension.

This is pretty robust to nasty input. It complies with your request for "the first 4 integers in a string of input" by finding the first 4 integers in the input separated by ANY non-numerical characters.

import re

def getMove(playerInput):
    m = re.search('([\d]+)[\D]*([\d]+)[\D]*([\d]+)[\D]*([\d]+)[\D]*', playerInput)
    if m:
        nums = [int(x) for x in m.groups()]
    else:
        raise ValueError("Invalid argument")
    return ((nums[0], nums[1]),(nums[2], nums[3]))

Examples of input/output:

Input: "((12,5wf),(21,4xx))" Output: ((12, 5), (21, 4))

Input: "((0,1),(2,3))" Output: ((0, 1), (2, 3))

Input: " (0, 1),(2, 3)" Ouptut: ((0, 1), (2, 3))

Note: This will always try its best to get 4 numbers, so if the input is (12, 5, 4) instead of raising the ValueError it will choose 1, 2, 5, and 4 as the numbers. If you come up with more strict requirements on the input format, the regular expression match can be tweaked to avoid this problem. If I'm misinterpreting your input format let me know and I can fix the expression to avoid this behavior.

Sign up to request clarification or add additional context in comments.

4 Comments

Great!, This works perfectly. Exactly what I was looking for, thank you very much for helping me out with this.
@methodMan You're very welcome. Please see the note I added to my answer. The behavior described can be modified if you'd like.
@methodMan Also, here's a great reference on using regular expressions in Python: docs.python.org/howto/regex.html and I recommend using a tool while you're writing expressions to make testing easier: erik.eae.net/playground/regexp/regexp.html
Interesting, I've never really looked into regular expressions because they always confused me but this actually explains it pretty well, and I can understand your code now. I can see how they can be very useful in many different applications.
1

Try this:

r = [int(c) for c in playerInput[:4]]
while len(r) < 4:
    r.append(0)
x1, y1, x2, y2 = r
return ((x1, y1), (x2, y2))

5 Comments

What does the "+ [0, 0, 0, 0]" do in your snippet?
It appends four zeros to the result of the first list comprehension in case it is too short. See my updated answer for a more explicit way to do this.
Ah, I see. In case len(playerInput) < 4.
These work if my input is just ints but what if my input is "(1,1) (1,2)"?
Unfortunately this doesn't work now that methodMan updated the requirement to work with different separators. A solution with regular expressions will likely be the most simple and robust.
0

regexxy:

import re
def bla(playerInput):
    m = re.match('.*?(\d{1,4}).*', playerInput)
    if m != None:
        x1, x2, x3, x4 = [int(c) for c in m.group(1).ljust(4, '0')]
        return ((x1, x2), (x3, x4))
    else:
        raise Exception("invalid Input")

its a little more tolerant, it takes the first 1 to 4 digits in the string and fill with 0s.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.