Elegant way to concat all dict values together with a string carrier as a single string in Python

Question:

The objective is to concat all values in a dict into a single str.

Additionally, the rn also will be appended.

The code below demonstrates the end result.

However, I am looking for a more elegant alternative than the proposed code below.

d=dict(idx='1',sat='so',sox=[['x1: y3'],['x2: y1'],['x3: y3']],mul_sol='my love so')

s=''
for x in d:
    if x=='sox':
        for kk in d[x]:
            s=s +kk[0] +'rn'
    else:

        s=s +d[x]+'rn'
print(s)
Asked By: rpb

||

Answers:

Use two generators, one for d['sox'] and another for everything else, and then use join() to concatenate strings.

s = ''.join(kk[0] for kk in d['sox']) + 'rn'
s += 'rn'.join(val for key, val in d.items() if key != 'sox')
Answered By: Barmar

following code have more control over what might have in the dictionary:

def conca(li):
  ret=''
  for ele in li:
    if isinstance(ele,str):
        ret += ele + 'rn'
    else:
        ret += conca(ele) 
  return ret

print(conca([d[e] for e in list(d)]))

or if want a more versatile solution:

def conca(li):
 ret = ''
 for ele in li:
    if isinstance(ele, str):
        ret += ele + 'rn'
    elif isinstance(ele, list):
        ret += conca(ele)
    elif isinstance(ele, dict):
        ret += conca(ele.values())
    # you can add any other customized conversions here...
    else:
        raise Exception(
            "value of dictionary can only be str, list or dict~")
 return ret
print(conca([d[e] for e in list(d)]))
Answered By: shan

Make a separate function that transforms the values, and then apply that using map.

d = {
    'idx': '1',
    'sat': 'so',
    'sox': [['x1: y3'],['x2: y1'],['x3: y3']],
    'mul_sol': 'my love so'
}

crlf = 'rn'

import operator

def transform_sox(item):
    (key, val) = item
    if key == 'sox':
        return crlf.join(map(operator.itemgetter(0), val))
    else:
        return val

print(crlf.join(map(transform_sox, d.items())), crlf)

Not necessarily shorter, but clearer and more maintainable in my opinion.


Alternatively, if we can rely on the value type to determine the transformation, rather than the key:

def transform_sox(value):
    return value if isinstance(value, str) 
        else crlf.join(map(operator.itemgetter(0), value))

print(crlf.join(map(transform_sox, d.values())), crlf)

In the other direction, perhaps you need custom formatters for a few elements in the dictionary. In which case, look up the formatter for each element:

formatters = collections.defaultdict(lambda: lambda x: x)
formatters['sox'] = lambda x: crlf.join(map(operator.itemgetter(0), x))

def transform_sox(item):
    return formatters[item[0]](item[1])

print(crlf.join(map(transform_sox, d.items())), crlf)
Answered By: Toby Speight
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.