Check If A String Is Hexadecimal
Solution 1:
(1) Using int() works nicely for this, and Python does all the checking for you :)
int('00480065006C006C006F00200077006F0072006C00640021', 16)
6896377547970387516320582441726837832153446723333914657L
will work. In case of failure you will receive a ValueError
exception.
Short example:
int('af', 16)
175int('ah', 16)
...
ValueError: invalid literal forint() withbase 16: 'ah'
(2) An alternative would be to traverse the data and make sure all characters fall within the range of 0..9
and a-f/A-F
. string.hexdigits
('0123456789abcdefABCDEF'
) is useful for this as it contains both upper and lower case digits.
importstring
all(c in string.hexdigits for c in s)
will return either True
or False
based on the validity of your data in string s
.
Short example:
s = 'af'
all(c in string.hexdigits for c in s)
True
s = 'ah'
all(c in string.hexdigits for c in s)
False
Notes:
As @ScottGriffiths notes correctly in a comment below, the int()
approach will work if your string contains 0x
at the start, while the character-by-character check will fail with this. Also, checking against a set of characters is faster than a string of characters, but it is doubtful this will matter with short SMS strings, unless you process many (many!) of them in sequence in which case you could convert stringhexditigs to a set with set(string.hexdigits)
.
Solution 2:
You can:
- test whether the string contains only hexadecimal digits (0…9,A…F)
- try to convert the string to integer and see whether it fails.
Here is the code:
import string
defis_hex(s):
hex_digits = set(string.hexdigits)
# if s is long, then it is faster to check against a setreturnall(c in hex_digits for c in s)
defis_hex(s):
try:
int(s, 16)
returnTrueexcept ValueError:
returnFalse
Solution 3:
I know the op mentioned regular expressions, but I wanted to contribute such a solution for completeness' sake:
defis_hex(s):
return re.fullmatch(r"^[0-9a-fA-F]$", s or"") isnotNone
Performance
In order to evaluate the performance of the different solutions proposed here, I used Python's timeit module. The input strings are generated randomly for three different lengths, 10
, 100
, 1000
:
s=''.join(random.choice('0123456789abcdef') for _ in range(10))
Levon's solutions:
# int(s, 16)10:0.257451018987922100:0.400816908018896361000:1.8926858339982573# all(_ in string.hexdigits for _ in s)10:1.2884491360164247100:10.0477179479785261000:94.35805322701344
Other answers are variations of these two. Using a regular expression:
# re.fullmatch(r'^[0-9a-fA-F]$', s or '')10:0.725040541990893100:0.71842728200135751000:0.7190397029917222
Picking the right solution thus depends on the length on the input string and whether exceptions can be handled safely. The regular expression certainly handles large strings much faster (and won't throw a ValueError
on overflow), but int()
is the winner for shorter strings.
Solution 4:
One more simple and short solution based on transformation of string to set and checking for subset (doesn't check for '0x' prefix):
import string
defis_hex_str(s):
returnset(s).issubset(string.hexdigits)
More information here.
Solution 5:
Another option:
defis_hex(s):
hex_digits = set("0123456789abcdef")
for char in s:
ifnot (char in hex_digits):
returnFalsereturnTrue
Post a Comment for "Check If A String Is Hexadecimal"