views:

139

answers:

5

I want to break a Python string into its characters.

sequenceOfAlphabets = list( string.uppercase )

works.

However, why does not

sequenceOfAlphabets = re.split( '.', string.uppercase )

work?

All I get are empty, albeit expected count of elements

+2  A: 

Because the delimiter character used by split does not appear in the resulting list. This allows it be used like:

re.split(',', "foo,bar,baz")
['foo', 'bar', 'baz']

Also, you will find the resulting list from your split code actually contains one extra element, since split returns one more than the number of delimiters found. The above has two commas, so it returns a three-element list.

Matthew Flaschen
A: 

From the documentation:

If capturing parentheses are used in pattern, then the text of all groups in the pattern are also returned as part of the resulting list.

Also note:

If there are capturing groups in the separator and it matches at the start of the string, the result will start with an empty string. The same holds for the end of the string.

So, use re.split( '(.)', string.uppercase)[1:-1] instead.

Brian
That still gives unnecessary empty characters.
Matthew Flaschen
I mentioned the relevant documentation in my response. It does so consistently, so they're easily removable. That said, it's simple enough to just use `re.split( '(.)', string.uppercase)[1:-1]` to get rid of them. Updating my answer.
Brian
+4  A: 

The '.' matches every character and re.split returns everything that wasn't matched, that's why you're getting the empty list.

Using list is usually the way to handle something like this but if you want to use regular expressions just use re.findall

sequenceOfAlphabets = re.findall( '.', string.uppercase )

That should give you ['A', 'B', 'C', .... ,'Z']

John
A very precise and well written answer John. Keep it up!
PoorLuzer
-1 Imprecise and wrong. See my answer.
John Machin
It's wrong *only* if we are interested in extracting embedded newlines as well. Besides that, it's *still* precise!
PoorLuzer
"The '.' matches every character" is wrong, irrespective of anybody's intent.
John Machin
A: 

Just an FYI, this also works:

sequenceOfAlphabets = [a for a in string.uppercase]

...but that does exactly what list() would do so I don't think it would be any faster (I could be wrong).

Dan McDougall
+1  A: 

If you can do something with both a built-in function and with regexes, then usually the built-in approach will be faster and more legible.

The regex world is a maze of twisty little passages, populated by purveyors of almost-truths like """The '.' matches every character""" ... which it does, but only when you use the re.DOTALL flag. This information is not cunningly concealed in the fine print of the documentation; it's right there as the FIRST entry of "special characters":

'.'
(Dot.) In the default mode, this matches any character except a newline. If the DOTALL flag has been specified, this matches any character including a newline.

>>> import re
>>> re.findall(".", "fu\nbar")
['f', 'u', 'b', 'a', 'r']
>>>
John Machin
Did you comment on John's answer being incorrect because it would not return the '\n'? In that case you would be right, though pedantic, as my *intention* had been to get the run of alphabets, but never put that into words.
PoorLuzer
(1) Saying that "matches every character" is not the same as "matches any character except a newline" is pedantic?? (2) I'm guessing based on a google search for "run of alphabets" that "alphabets" is HK English for "alphabetic characters" but what is "*THE* run of alphabets"? Is '\n' an "alphabet" or a "non-alphabet"?
John Machin