Home > Mobile >  get index at 0,1,list/2,(list/2 1),2,3
get index at 0,1,list/2,(list/2 1),2,3

Time:01-06

I have a list of dicts and I wants to get the elements at index `0,1,list/2,(list/2 1),2,3,....

As an example i have following list of dicts.

test = [{'aa':0},{'ab':0},{'ba':0},{'bb':0},{'ca':0},{'cb':0},{'da':0},{'db':0},{'ea':0},{'eb':0},{'fa':0},{'fb':0}]
output: [{'aa':0},{'ab':0},{'da':0},{'db':0},{'ba':0},{'bb':0},{'ea':0},{'eb':0},{'ca':0},{'cb':0},{'fa':0},{'fb':0}]

Is there an easy way to do this? If is do sommeting like this.

[item for sublist in zip(test[:middel], test[middel:]) for item in sublist]

I get following output.

[{'aa':0},
 {'da':0},
 {'ab':0},
 {'db':0},
 {'ba':0},
 {'ea':0},
 {'bb':0},
 {'eb':0},
 {'ca':0},
 {'fa':0},
 {'cb':0},
 {'fb':0}]

if I split test in 2 (in the middle)

list1 = [{'aa': 0}, {'ab': 0}, {'ba': 0}, {'bb': 0}, {'ca': 0}, {'cb': 0}]
list2 = [{'da': 0}, {'db': 0}, {'ea': 0}, {'eb': 0}, {'fa': 0}, {'fb': 0}]

I wants a new list with the first 2 dicts of list1, then the 2 first of list2, then the middle 2 of list1, then the middle 2 of list2 then the last 2 of list1, then the last 2 of list2

The real dicts does look like this

{'datasource': 'InfluxDB', 'fieldConfig': {'defaults': {'mappings': [], 'thresholds': {'mode': 'absolute', 'steps': [{'color': 'yellow', 'value': None}, {'color': 'green', 'value': 50}, {'color': 'red', 'value': 400}]}, 'unit': 'kwatt'}, 'overrides': []}, 'gridPos': {'h': 5, 'w': 4, 'x': 14, 'y': 14}, 'id': 104, 'options': {'colorMode': 'background', 'graphMode': 'none', 'justifyMode': 'auto', 'orientation': 'horizontal', 'reduceOptions': {'calcs': ['lastNotNull'], 'fields': '', 'values': False}, 'text': {'titleSize': 16, 'valueSize': 16}, 'textMode': 'auto'}, 'pluginVersion': '8.1.1', 'targets': [{'alias': 'Gevraagd vermogen', 'groupBy': [{'params': ['$__interval'], 'type': 'time'}, {'params': ['null'], 'type': 'fill'}], 'orderByTime': 'ASC', 'policy': 'default', 'refId': 'B', 'resultFormat': 'time_series', 'select': [[{'params': ['GV'], 'type': 'field'}, {'params': [], 'type': 'last'}, {'params': [' / 10'], 'type': 'math'}]], 'tags': []}, {'alias': 'Geleverd vermogen', 'groupBy': [{'params': ['$__interval'], 'type': 'time'}, {'params': ['null'], 'type': 'fill'}], 'orderByTime': 'ASC', 'policy': 'default', 'refId': 'A', 'resultFormat': 'time_series', 'select': [[{'params': ['Actief vermogen'], 'type': 'field'}, {'params': [], 'type': 'last'}]], 'tags': []}], 'timeFrom': None, 'timeShift': None, 'type': 'stat'}

CodePudding user response:

You example is a bit complex and can be simplified to:

Change this input:

i = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

into this output:

o = [0, 1, 6, 7, 2, 3, 8, 9, 4, 5, 10, 11]

using the algorithm you describe.

This can be achieved easily using iterators:

def reorder(l, by=2):
    half = len(l)//2
    a, b = iter(l[:half]), iter(l[half:])
    out = []
    for i in range(len(l)//(2*by)):
        for i in range(by):
            out.append(next(a))
        for i in range(by):
            out.append(next(b))
    return out
    
o = reorder(i)

on the provided data:

>>> reorder(test)
[{'aa': 0},
 {'ab': 0},
 {'da': 0},
 {'db': 0},
 {'ba': 0},
 {'bb': 0},
 {'ea': 0},
 {'eb': 0},
 {'ca': 0},
 {'cb': 0},
 {'fa': 0},
 {'fb': 0}]

CodePudding user response:

new_list = []
l_2 = int(len(test) / 2)
for one, two, mid_one, mid_two in zip(test[:l_2:2], test[1:l_2:2], test[l_2::2], test[1   l_2 :: 2]):
    new_list.append(one)
    new_list.append(two)
    new_list.append(mid_one)
    new_list.append(mid_two)
print(new_list)

CodePudding user response:

I see a brute force solution...

output = []
for c1 in 'aedbcf':
    for c2 in 'ab':
        output.append({c1 c2 : 0}) 
print(output)

Otherwise, the trick you need is to pair up your elements on the first letters before you try to rearrange them, not directly slice your initial list

CodePudding user response:

I think this can be a solution that avoids a for loop:

from itertools import pairwise

inputs = [1, 2, 3, 4, 5, 6, 7, 8]
pair = list(pairwise(inputs)) # -> [(1, 2), (2, 3), (3, 4), ...]
del pair[1::2] # remove [(2, 3), (4, 5), ...]
first, second = pair[:len(pair)//2], pair[len(pair)//2:] # first = [(1, 2), (3, 4)], second = [(5, 6), (7, 8)]

def merge_tuple(x):
    return x[0]   x[1]

output = list(map(merge_tuple, zip(first, second))) # -> [(1, 2, 5, 6), (3, 4, 7, 8)]
output = output[0]   output[1]

If your python version is too old to have pairwise you can use this

  •  Tags:  
  • Related