Home > Net >  Adding "sequential" information to python list using dictionaries
Adding "sequential" information to python list using dictionaries

Time:05-19

The problem

I would like to create a dictionary of dicts out of a flat list I have in order to add a "sequentiality" piece of information, but I am having some trouble finding a solution.

The list is something like

a = ['Q=123', 'W=456', 'E=789', 'Q=753', 'W=159', 'E=888']

and I am shooting for a dict like:

dictionary = {
    'Step_1': {
        'Q=123', 
        'W=456', 
        'E=789'
    },
    'Step_2': {
        'Q=753', 
        'W=159', 
        'E=888'
    }
}

I would like to end up with a function with an arbitrary number of Steps, in order to apply it to my dataset. Suppose that in the dataset there are lists like a with 1 <= n <6 Steps each.

My idea

Up to now, I came up with this:

nsteps = a.count("Q")
data = {}
for i in range(nsteps):
    stepi = {}
    for element in a:
            new = element.split("=")
            if new[0] not in stepi:
                stepi[new[0]] = new[1]
            else:
                pass
    data[f"Step_{i}"] = stepi

but it doesn't work as intended: both steps in the final dictionary contain the data of Step_1. Any idea on how to solve this?

CodePudding user response:

One way would be:

a = ['Q=123', 'W=456', 'E=789', 'Q=753', 'W=159', 'E=888']

indices = [i for i, v in enumerate(a) if v[0:2] == 'Q=']

dictionary = {f'Step_{idx 1}': {k: v for k, v in (el.split('=') for el in a[s:e])} 
              for idx, (s, e) in enumerate(zip(indices, indices[1:]   [len(a)]))}

print(dictionary)
{'Step_1': {'Q': '123', 'W': '456', 'E': '789'}, 
'Step_2': {'Q': '753', 'W': '159', 'E': '888'}}

Details:

a = ['Q=123', 'W=456', 'E=789', 'Q=753', 'W=159', 'E=888']

# Get indices where a step starts. 
# This could handle also steps with variable amount of elements and keys starting with 'Q' that are not exactly 'Q'.
indices = [i for i, v in enumerate(a) if v[0:2] == 'Q=']

# Get the slices of the list starting at Q and ending before the next Q.
slices = list(zip(indices, indices[1:]   [len(a)]))
print(slices)
# [(0, 3), (3, 6)]

# Get step index and (start, end) pair for each slice.
idx_slices = list(enumerate(slices))
print(idx_slices)
# [(0, (0, 3)), (1, (3, 6))]

# Split the strings in the list slices and use the result as key-value pair for a given start:end.
# Here an example for step 1:
step1 = idx_slices[0][1] # This is (0, 3).
dict_step1 = {k: v for k, v in (el.split('=') for el in a[step1[0]:step1[1]])}
print(dict_step1)
# {'Q': '123', 'W': '456', 'E': '789'}

# Do the same for each slice.
step_dicts = {f'Step_{idx 1}': {k: v for k, v in (el.split('=') for el in a[s:e])}
              for idx, (s, e) in idx_slices}
print(step_dicts)
# {'Step_1': {'Q': '123', 'W': '456', 'E': '789'}, 'Step_2': {'Q': '753', 'W': '159', 'E': '888'}}

CodePudding user response:

You were almost there. The way you were counting the number of "Q"s was wrong and some lines of code had a wrong indentation (for instance data[f"Step_{i}"] = stepi)

a = ['Q=123', 'W=456', 'E=789', 'Q=753', 'W=159', 'E=888']


def main():
    nsteps = len([s for s in a if "Q" in s])
    data = {}
    for i in range(nsteps):
        stepi = {}
        for element in a:
            new = element.split("=")
            if new[0] not in stepi:
                stepi[new[0]] = new[1]
            data[f"Step_{i}"] = stepi

    return data

if __name__ == "__main__":
    data = main()

CodePudding user response:

First group by items like this:

a = ['Q=123', 'W=456', 'E=789', 'Q=753', 'W=159', 'E=888']
o = groupby(sorted(a, key=lambda x: x[0]), key=lambda x: x[0])

then create a dictionary like this:

d = {i: [j[1] for j in g] for i, g in o}

then iterate over them and make your result:

result = {f"step_{i 1}": [v[i] for v in r.items()] for i in range(len(max(r.values(), key=len)))}

the result will be:

Out[47]: {'step_1': ['E=789', 'Q=123', 'W=456'], 'step_2': ['E=888', 'Q=753', 'W=159']}

CodePudding user response:

From what I understood from your question:

We can group the items in the list, in this case, a group of three elements, and loop through them three at a time.

With some help from this answer:

from itertools import zip_longest

a = ['Q=123', 'W=456', 'E=789', 'Q=753', 'W=159', 'E=888']

def grouper(n, iterable):
    args = [iter(iterable)] * n
    return zip_longest(*args)

result = dict()

for i, d in enumerate(grouper(3, a), start=1):
    dict.update({f"Step_{i}": set(d)})

print(result)
{
    'Step_1': {'E=789', 'Q=123', 'W=456'}, 
    'Step_2': {'E=888', 'Q=753', 'W=159'}
}
  • Related