3

I have a dictionary like this,

{'A':[[1,30],[40,50],[60,79]]
 'B':[[2,23],[26,43],[59,119]]
 'C':[[1,100],[149,167],[199,250]]
  ...                             }

I had the MAX value which is 600. Is it possible to calculate the difference between each value in every list? Finally, I can get a dictionary like this

 {'A':[[31,39],[51,59],[80,600]]
     'B':[[24,25],[44,58],[120,600]]
     'C':[[101,148],[168,198],[251,600]]
      ...                             
                                     }

Let me explain how final output comes. The origin data is

'A':[[i1,i2],[i3,i4],[i5,i6]]

Max value is M,

For each list, final output will be like

'A':[[(i2)+1,(i3)-1],[(i4)+1,(i5)-1],[(i6)+1,M]]

It seems I need a for loop to get there. But I have no idea how to do this in dictionary.

Jiayu Zhang
  • 719
  • 7
  • 22

3 Answers3

2

You can try this:

d1 = {'A':[[1,30],[40,50],[60,79]],
      'B':[[2,23],[26,43],[59,119]],
      'C':[[1,100],[149,167],[199,250]]}

def split_l(iterable, n):
    return [iterable[i:i+n] for i in range(0, len(iterable), n)] 

d2 = {k:split_l([val + (-1)**idx for idx, val in enumerate(sum(v, [])[1:])] + [600], 2) for k,v in d1.items()} 

Or in more readable way:

d2 = {}
for k, v in d1.items():
    flat_v = sum(v, [])[1:]

    for idx, __ in enumerate(flat_v):
        flat_v[idx] += (-1)**idx
    flat_v.append(600)

    split_v = [flat_v[i:i+2] for i in range(0, len(flat_v), 2)]
    d2[k] = split_v

Results:

import pprint
pprint.pprint(d2)
{'A': [[31, 39], [51, 59], [80, 600]],
 'B': [[24, 25], [44, 58], [120, 600]],
 'C': [[101, 148], [168, 198], [251, 600]]}
MaximTitarenko
  • 886
  • 4
  • 8
2

YOu can you itertools.chain

>>> from itertools import chain
>>> d = {'A':[[1,30],[40,50],[60,79]], 'B':[[2,23],[26,43],[59,119]],}
>>> for key in d:
...     d[key] = zip(*[iter([each+((-1)**index) for index,each in enumerate(chain.from_iterable(d[key]))]+[600,])]*2)
...
>>> d
{'A': [(31, 39), (51, 59), (80, 600)], 'B': [(24, 25), (44, 58), (120, 600)]}

That is,

>>> chain.from_iterable(d['A'])
<itertools.chain object at 0x7f6a9dd69950>
>>> list(chain.from_iterable(d['A']))
[31, 39, 51, 59, 80, 600]

>>> iter(each for each in enumerate(chain.from_iterable(d[key])))
<generator object <genexpr> at 0x7f6a9dd804b0>
>>> zip(*[iter(each for each in enumerate(chain.from_iterable(d[key])))]*2)
[((0, 2), (1, 23)), ((2, 26), (3, 43)), ((4, 59), (5, 119))]
Keerthana Prabhakaran
  • 3,766
  • 1
  • 13
  • 23
2

keep in mind that in python you can swap values of two variables this way:

a, b = b, a

so your problem can be solved like this:

def my_func(a_dict, max):
    for row in a_dict.values():
        row[0][0], row[0][1], row[1][0], row[1][1], row[2][0], row[2][1] = \
        row[0][1]+1, row[1][0]-1, row[1][1]+1, row[2][0]-1, row[2][1]+1, max

One thing to notice is that there is no return ....
dictionary is mutable, so any change to a_dict will retain.
After calling my_func, the dictionary passed to the function will contain the result.


update
@MaximTitarenko told me that the number of inner lists in each row(row=a list associated with a key of the dictionary)may vary. so I wrote another script which works in that case:

def make_result(a_dict, max):
    for row in a_dict.values():
        for index in range(len(row)-1):
            row[index][0] = row[index][1] + 1
            row[index][1] = row[index+1][0] -1
        row[-1][0] = row[-1][1] + 1
        row[-1][1] = max
Shahryar Saljoughi
  • 2,599
  • 22
  • 41