I've got a list in a Python program that contains a series of numbers, which are themselves ASCII values. How do I convert this into a "regular" string that I can echo to the screen?
9 Answers
You are probably looking for 'chr()':
>>> L = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100] >>> ''.join(chr(i) for i in L) 'hello, world' 2 Comments
zapstar
I'll bet you created that list L using
[ord(x) for x in 'hello, world']FindOutIslamNow
chars = [chr(i) for i in range(97, 97 + 26)]Same basic solution as others, but I personally prefer to use map instead of the list comprehension:
>>> L = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100] >>> ''.join(map(chr,L)) 'hello, world' 1 Comment
Felix An
map() is marginally faster than a list comprehension.import array def f7(list): return array.array('B', list).tostring() Comments
You can use bytes(list).decode() to do this - and list(string.encode()) to get the values back.
2 Comments
user333869
This solution looks the easiest to me
stackyi
While the top voted solution works, this is the most elegant solution.
def working_ascii(): """ G r e e t i n g s ! 71, 114, 101, 101, 116, 105, 110, 103, 115, 33 """ hello = [71, 114, 101, 101, 116, 105, 110, 103, 115, 33] pmsg = ''.join(chr(i) for i in hello) print(pmsg) for i in range(33, 256): print(" ascii: {0} char: {1}".format(i, chr(i))) working_ascii() Comments
I've timed the existing answers. Code to reproduce is below. TLDR is that bytes(seq).decode() is by far the fastest. Results here:
test_bytes_decode : 12.8046 μs/rep test_join_map : 62.1697 μs/rep test_array_library : 63.7088 μs/rep test_join_list : 112.021 μs/rep test_join_iterator : 171.331 μs/rep test_naive_add : 286.632 μs/rep Setup was CPython 3.8.2 (32-bit), Windows 10, i7-2600 3.4GHz
Interesting observations:
- The "official" fastest answer (as reposted by Toni Ruža) is now out of date for Python 3, but once fixed is still basically tied for second place
- Joining a mapped sequence is almost twice as fast as a list comprehension
- The list comprehension is faster than its non-list counterpart
Code to reproduce is here:
import array, string, timeit, random from collections import namedtuple # Thomas Wouters (https://stackoverflow.com/a/180615/13528444) def test_join_iterator(seq): return ''.join(chr(c) for c in seq) # community wiki (https://stackoverflow.com/a/181057/13528444) def test_join_map(seq): return ''.join(map(chr, seq)) # Thomas Vander Stichele (https://stackoverflow.com/a/180617/13528444) def test_join_list(seq): return ''.join([chr(c) for c in seq]) # Toni Ruža (https://stackoverflow.com/a/184708/13528444) # Also from https://www.python.org/doc/essays/list2str/ def test_array_library(seq): return array.array('b', seq).tobytes().decode() # Updated from tostring() for Python 3 # David White (https://stackoverflow.com/a/34246694/13528444) def test_naive_add(seq): output = '' for c in seq: output += chr(c) return output # Timo Herngreen (https://stackoverflow.com/a/55509509/13528444) def test_bytes_decode(seq): return bytes(seq).decode() RESULT = ''.join(random.choices(string.printable, None, k=1000)) INT_SEQ = [ord(c) for c in RESULT] REPS=10000 if __name__ == '__main__': tests = { name: test for (name, test) in globals().items() if name.startswith('test_') } Result = namedtuple('Result', ['name', 'passed', 'time', 'reps']) results = [ Result( name=name, passed=test(INT_SEQ) == RESULT, time=timeit.Timer( stmt=f'{name}(INT_SEQ)', setup=f'from __main__ import INT_SEQ, {name}' ).timeit(REPS) / REPS, reps=REPS) for name, test in tests.items() ] results.sort(key=lambda r: r.time if r.passed else float('inf')) def seconds_per_rep(secs): (unit, amount) = ( ('s', secs) if secs > 1 else ('ms', secs * 10 ** 3) if secs > (10 ** -3) else ('μs', secs * 10 ** 6) if secs > (10 ** -6) else ('ns', secs * 10 ** 9)) return f'{amount:.6} {unit}/rep' max_name_length = max(len(name) for name in tests) for r in results: print( r.name.rjust(max_name_length), ':', 'failed' if not r.passed else seconds_per_rep(r.time)) 2 Comments
Empty Space
Also include the python implementation you are using since that can affect the benchmark numbers. Here is how you can retrieve that information stackoverflow.com/a/14718168/12160191.
user13528444
@MutableSideEffect Done. I know offhand that it’s CPython, but I had no idea you could find that programmatically
Question = [67, 121, 98, 101, 114, 71, 105, 114, 108, 122] print(''.join(chr(number) for number in Question)) 1 Comment
Cindy Meister
Please note that on Stack Overflow it is customary to include some explanation of why the proposed approach answers the question - especially when the question is older and already has an accepted answer. In what way does this suggestion differ and why would it be used instead of an existing answer?