Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Background

I have a string in Python which I want to convert to an integer. Normally, I would just use int:

>>> int("123")
123

Unfortunately, this method is not very robust, as it only accepts strings that match -?[0-9]+ (after removing any leading or trailing whitespace). For example, it can't handle input with a decimal point:

>>> int("123.45")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '123.45'

And it certainly can't handle this:

>>> int("123abc?!")

On the other hand, exactly this behavior can be had without any fuss in Perl, PHP, and even the humble QBasic:

INT(VAL("123abc"))   ' 123

Question

Here's my shortest effort at this "generalized int" in Python. It's 50 bytes, assuming that the original string is in s and the result should end up in i:

n="";i=0
for c in s:
 n+=c
 try:i=int(n)
 except:0

Fairly straightforward, but the try/except bit is ugly and long. Is there any way to shorten it?

Details

Answers need to do all of the following:

  • Start with a string in s; end with its integer value in i.
  • The integer is the first run of digits in the string. Everything after that is ignored, including other digits if they come after non-digits.
  • Leading zeros in the input are valid.
  • Any string that does not start with a valid integer has a value of 0.

The following features are preferred, though not required:

  • A single - sign immediately before the digits makes the integer negative.
  • Ignores whitespace before and after the number.
  • Works equally well in Python 2 or 3.

(Note: my code above meets all of these criteria.)

Test cases

"0123"   -> 123
"123abc" -> 123
"123.45" -> 123
"abc123" -> 0
"-123"   -> -123 (or 0 if negatives not handled)
"-1-2"   -> -1 (or 0 if negatives not handled)
"--1"    -> 0
""       -> 0
share|improve this question
    
Somewhat related: codegolf.stackexchange.com/questions/28783/… (but there it was explicitly stated that input would be properly-formed integers). –  DLosc yesterday
1  
What should "12abc3" give? –  orlp 22 hours ago
    
@orlp 12--it's analogous to the "123.45" case. –  DLosc 21 hours ago
    
(lambda(x)(or(parse-integer x :junk-allowed t)0)) (Common Lisp, 49 bytes) -- Only posted as a comment since it is built-in. –  coredump 17 hours ago
1  
@coredump :junk-allowed--ha, that's great! I would have made this a general golf challenge, were it not for the fact that the answer in many languages is trivial. But thanks for the Lisp. :^) –  DLosc 14 hours ago

2 Answers 2

Python 2, 47

It's not as short as using regex, but I thought it was entertainingly obscure.

i=int(('0%sx'%s)[:~len(s.lstrip(`1/81.`[9:]))])
share|improve this answer
1  
you can shave off a byte by using str(1<<68) inside the lstrip –  KSab 20 hours ago
    
Wow. Entertainingly obscure is right! (This only handles nonnegative numbers, correct?) –  DLosc 13 hours ago
    
Another bonus of @KSab's suggestion is Python 3 compatibility. –  DLosc 13 hours ago

40 bytes

import re;i=int("0"+re.split("\D",s)[0])

and you can do negatives for 8 characters more:

import re;i=int((re.findall("^-?\d+",s)+[0])[0])
share|improve this answer
    
Your second solution fails on input like "abc123" (gives 123, not 0) and "abc" (gives IndexError because findall returns empty list). I think both of those problems are fixable, though--and the first solution looks solid. My best regex solution was 57 bytes. Kudos! –  DLosc 21 hours ago
    
@DLosc Ah you're right, didn't test the second one well enough apparently. The 'aha' moment was when I realized some python regex functions return strings not MatchObjects –  KSab 21 hours ago
1  
import re;i=int((re.findall("^-?\d+",s)+[0])[0]) works, for 48 bytes. –  DLosc 13 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.