2

What is a neat way to remove different characters from a string? For example, I have the following strings that I need to convert to integers:

($12,990)
$21,434

I use the following code which works fine, but is there a less bulkier way to do the same?

string = string.replace(",", "")
string = string.replace("$", "")
string = string.replace("(", "-")
string = string.replace(")", "")
int(string)

Edit: I am using Python 2.7.

sprogissd
  • 2,755
  • 5
  • 24
  • 45
  • is `string.replace("(", "-")` a typo? That line doesn't remove a character... – MSeifert Jul 12 '17 at 22:35
  • 1
    @MSeifert It's Excel formatting for negative numbers to put parenthesis around them – OneCricketeer Jul 12 '17 at 22:37
  • [This answer](https://stackoverflow.com/a/15448887/223424) is most concise, but the whole thread is excellent, and shows that the problem is not entirely trivial. – 9000 Jul 12 '17 at 22:44
  • 1
    @9000 only if `-` were both a value to be replaced and a value to replace. `str.translate` handles this nicely (and trivially). The question you marked as a duplicate does not seem to use `str.translate` at all. – Adam Smith Jul 12 '17 at 22:45
  • 1
    @AdamSmith: Yes, for one-character case, `str.translate` is nice. This may suffice in this particular case. – 9000 Jul 12 '17 at 22:47

3 Answers3

7

You could use str.translate, e.g.

>>> "($12,990)".translate(str.maketrans({',': '', '$': '', '(': '-', ')': ''}))
'-12990'

As stated by @AdamSmith in the comments you could also utilize the (full) three-argument form of str.maketrans:

>>> translationtable = str.maketrans("(", "-", ",$)")
>>> "($12,990)".translate(translationtable)
'-12990'

In case you're using python-2.x the str.translate function and string.maketrans function can be used:

>>> import string
>>> translationtable = string.maketrans('(', '-')
>>> "($12,990)".translate(translationtable, ',$)')
'-12990'

or with unicodes on Python-2.x you need a unicode-ordinal to unicode-ordinal/string or None:

>>> unicode_translation_table = {ord(u','): None, ord(u'$'): None, ord(u'('): ord(u'-'), ord(u')'): None}
>>> u"($12,990)".translate(unicode_translation_table)
u'-12990'
MSeifert
  • 145,886
  • 38
  • 333
  • 352
  • 1
    or `str.maketrans("(", "-", ",$)")` [per the docs](https://docs.python.org/3/library/stdtypes.html#str.maketrans) the three-argument version of `maketrans` pairs the first two arguments and maps the third to `None` (empty string) – Adam Smith Jul 12 '17 at 22:42
  • I am getting an error `AttributeError: type object 'str' has no attribute 'maketrans'`. I guess that is because I am using Python 2.7. Is there a way to make it work in Python 2.7? – sprogissd Jul 13 '17 at 02:15
  • @sprogissd I included the python 2.7 way of solving it :) – MSeifert Jul 13 '17 at 10:05
  • I get this error `translate() takes exactly one argument (2 given)` when I use your solution in Python 2.7 and use a string variable instead of `"($12,990)"`. – sprogissd Jul 13 '17 at 18:52
  • Seems like the error is caused by unicode. When I do `string.encode('utf-8')`, it works. Is there a way to do it using unicode? – sprogissd Jul 13 '17 at 18:56
  • @sprogissd I updated the answer (again) :) – MSeifert Jul 13 '17 at 19:41
  • Thank you. It doesn't look neat anymore though. I guess I will stick with `.encode('utf-8')`. – sprogissd Jul 13 '17 at 20:23
0

Well, you can rely on a loop to make it less ugly:

FORBIDDEN_CHARS =  { # Model: { "Replacer" : "Replacees", ... }
 "" : ",$)", 
 "-" : "("
} 

for replacer in FORBIDDEN_CHARS:
 for replacee in FORBIDDEN_CHARS[replacer]:
  mystr = mystr.replace(replacee, replacer)
Fabien
  • 4,862
  • 2
  • 19
  • 33
-1
''.join(string.strip('(').strip(')').strip('$').split(','))

or

''.join(filter(str.isdigit, string))
Dan
  • 1,874
  • 1
  • 16
  • 21