Joining array to string from list comprehension results in join between all characters

146 views Asked by At

So I have the following dict (the reason it's a dict and not a list is due to the output of the queryparams-parser django package parsing POST values:

doctor_times = {
    '1': {
        'id': 'ABC',
    },
    '2': {
        'id': 'DEF',
    },
}

The plan is to merge these to a string such as "'ABC', 'DEF'" for which I thought the following code would do:

doctorcodes = ', '.join("'%s'" % [str(doctor_times[k]['id']) for k in doctor_times.keys()])

However this results in:

"[, ', A, B, C, ', ,,  , ', D, E, F, ', ]"

If I remove the '%s' % component however it works fine, but I do need them wrapped individually in quotes.

3

There are 3 answers

4
thefourtheye On BEST ANSWER

The problem with your code is that, you are passing the entire list to '%s' % part. Instead move it only to the string part like this.

print ', '.join(['%s' % str(doctor_times[k]['id']) for k in doctor_times.keys()])

and you don't need to format the data to str again with %s. So, it becomes like this

print ', '.join(str(doctor_times[k]['id']) for k in doctor_times.keys())

This could be further simplified like this

print ", ".join(str(v['id']) for v in doctor_times.values())
3
Abhijit On

You may take a more generic approach by nesting the call to dict.values on the values of the dictionary. What you have is a two depth nested dictionary, but arbitrary depth, the following solution can easily be adopted

>>> ','.join(str(e[0]) for e in map(dict.values, doctor_times.values()))
'ABC,DEF'

or if you prefer itertools

>>> from itertools import imap, chain
>>> ', '.join(map(str, chain.from_iterable(imap(dict.values, doctor_times.values()))))
'ABC, DEF'
4
Blckknght On

I think you may want:

", ".join(repr(v["id"]) for v in doctor_times.values())

This will join the values in an arbitrary order though. If you want the order to be consistent (always "'ABC', 'DEF'" and never "'DEF', 'ABC'"), you may instead need to sort the dictionary items, rather than just iterating over the values directly:

", ".join(repr(v["id"]) for k, v in sorted(doctor_times.items()))

There is one more potential issue with this code. If some of your strings have single quote characters in them (and no double quote characters), their repr will use double quotes, rather than single ones. If a string includes both single and double quotes, the single quote characters will be escaped with \. If the joined string needs to follow some specific convention (such as the rules of a programming language or a data protocol), you may need to use your own escaping code, rather than relying on repr.