You can do the following:
dict1 = {'index': 'cfs_nucleus_bespoke_88260', 'host': 'iaasn00018224.svr.us.jpmchase.net', 'source': '/logs/tomcat7inst0/localhost_tomcat7inst0_access_log2018-11-02.txt', '_time': '2018-11-02 19:46:50.000 EDT', 'count': '1'}
d1_items = list(dict1.items())
col_width = 2
dict2 = {f'column{col_num // col_width + 1}': {k: v for k, v in d1_items[col_num:col_num + col_width]} for col_num in range(0, len(dict1), col_width)}
Try it online!
There are a few moving parts that interact to create this solution:
Python has a neat trick where it allows you to embed for in
loops in iterable and dict declarations to efficiently cycle and modify a set of elements. Here, the outer iterator is range(0, len(dict1), col_width)
: this goes through a sequence of integers starting from 0, and progressively increases by col_width
until it is greater than or equal to the size of the list, which functions to choose the start index of each col_width
-sized dict segment.
Tuple unpacking
dict1.items()
is convenient because it returns a dict view of 2-tuples of each dictionary key and its value. Later, we utilize tuple unpacking k: v for k, v in d1_items[ ... ]
, where a tuple of variables is flattened into two variables that can then easily form a key-value pair of the currrent dictionary comprehension. (This is only in newer versions of Python.)
d1_items[col_num:col_num + col_width]
is basically a way of getting a sublist. The syntax in relatively straightforward: starting from position col_num
, get a sublist up to and excluding the element col_num + col_width
(i.e. a sublist of size col_width
).
Preceding a string with f
makes it a formatted string literal. Anything within {
}
is interpreted as literal Python syntax (with the exception of '
, {
, and }
, which may vary behavior by context.) Here, in f'column{col_num // col_width + 1}'
, it allows us to label each column with a bit of division and a +1 offset to start counting from 1 instead of 0. (This is new to Python 3.6)