I am working in Python 2 and I have a string containing emojis as well as other unicode characters. I need to convert it to a list where each entry in the list is a single character/emoji.
x = u'
I am working in Python 2 and I have a string containing emojis as well as other unicode characters. I need to convert it to a list where each entry in the list is a single character/emoji.
x = u'
I would use the uniseg library (
pip install uniseg
):First of all, in Python2, you need to use Unicode strings (
u'<...>'
) for Unicode characters to be seen as Unicode characters. And correct source encoding if you want to use the chars themselves rather than the\UXXXXXXXX
representation in source code.Now, as per Python: getting correct string length when it contains surrogate pairs and Python returns length of 2 for single Unicode character string, in Python2 "narrow" builds (with
sys.maxunicode==65535
), 32-bit Unicode characters are represented as surrogate pairs, and this is not transparent to string functions. This has only been fixed in 3.3 (PEP0393).The simplest resolution (save for migrating to 3.3+) is to compile a Python "wide" build from source as outlined on the 3rd link. In it, Unicode characters are all 4-byte (thus are a potential memory hog) but if you need to routinely handle wide Unicode chars, this is probably an acceptable price.
The solution for a "narrow" build is to make a custom set of string functions (
len
,slice
; maybe as a subclass ofunicode
) that would detect surrogate pairs and handle them as a single character. I couldn't readily find an existing one (which is strange), but it's not too hard to write:0xD800..0xDBFF
0xDC00..0xDFFF
So here's the code to detect a surrogate pair:
And a function that returns a simple slice:
Here, the price you pay is performance, as these functions are much slower than built-ins: