简体   繁体   中英

Enumerate in nested for loop with list comprehension for inner increment

Following up on this question on how to implement enumerate within a list comprehension for an outer increment, I am wondering if there is a way to adjust the accepted answer in order to create an inner increment this time; I am looking to generate this output:

['D_50_1-1_1',
 'D_50_2-1_2',
 'D_50_3-1_3',
 'D_80_1-2_1',
 'D_80_2-2_2',
 'D_80_3-2_3',
 'D_20_1-3_1',
 'D_20_2-3_2',
 'D_20_3-3_3',
 'D_60_1-4_1',
 'D_60_2-4_2',
 'D_60_3-4_3',
 'E_35_1-5_1',
 'E_35_2-5_2',
 'E_35_3-5_3',
 'E_25_1-6_1',
 'E_25_2-6_2',
 'E_25_3-6_3']

where the inner increment is the second to last column ( 1,1,1,2,2,3,3,3...6,6,6 ).

At the moment, I achieve this by hard-coding the increment (eg. list(range(1, 4+1)) ) depending on the length of levelB , which is obviously prone to errors:

[f'{levelA}_{levelB}_{sub}-{inner_increment}_{sub}'
 for levelA, pairs in
          [('D',  dict(zip([50,80,20,60], list(range(1, 4+1))))),
           ('E',  dict(zip([35, 25],      list(range(5, 7+1)))))]
                                               
 for levelB,inner_increment in pairs.items()
 for sub in range(1, 3+1)
]

Is there a way to produce the same output by introducing enumerate while keeping the list comprehension approach and ideally wihhout any imports, similar to the accepted answer in the other question?

The tricky part is the partitioning of levelb. We have to enumerate over the whole thing once, but have a way to separate it so only parts of it get matched with each levela. Here's a version with some preliminary steps:

levela = 'D', 'E'
levelb = (50, 80, 20, 60), (35, 25)
levelc = 1, 2, 3

pairs = [
    (a, b)
    for a, partition in zip(levela, levelb)
    for b in partition
]

result = [
    (a, b, n, i)
    for i, (a, b) in enumerate(pairs, start=1)
    for n in (1, 2, 3)
]

actual = [f'{a}_{b}_{n}-{i}_{n}'.format(a, b, i, n) for a, b, n, i in result]

desired = ['D_50_1-1_1',
 'D_50_2-1_2',
 'D_50_3-1_3',
 'D_80_1-2_1',
 'D_80_2-2_2',
 'D_80_3-2_3',
 'D_20_1-3_1',
 'D_20_2-3_2',
 'D_20_3-3_3',
 'D_60_1-4_1',
 'D_60_2-4_2',
 'D_60_3-4_3',
 'E_35_1-5_1',
 'E_35_2-5_2',
 'E_35_3-5_3',
 'E_25_1-6_1',
 'E_25_2-6_2',
 'E_25_3-6_3']

for a, b in zip(result, desired):
    if a == b:
        print (a)
    else:
        print (a, b)

Not being able to use itertools is a pain.

I eventually managed to solve it myself. Posting for completeness.

[f'{levelA}_{levelB}_{sub}-{increment}_{sub}' 
      for increment, (levelA, levelB) in enumerate(
      (   
           (levelA,levelB)
           for levelA,lists in 
                  [('D',  [50,80,20,60]), 
                   ('E',  [35, 25])]
      for levelB in lists
      ), start=1,
      )
      for sub in range(1,3+1)
      ]
Out[67]: 
['D_50_1-1_1',
 'D_50_2-1_2',
 'D_50_3-1_3',
 'D_80_1-2_1',
 'D_80_2-2_2',
 'D_80_3-2_3',
 'D_20_1-3_1',
 'D_20_2-3_2',
 'D_20_3-3_3',
 'D_60_1-4_1',
 'D_60_2-4_2',
 'D_60_3-4_3',
 'E_35_1-5_1',
 'E_35_2-5_2',
 'E_35_3-5_3',
 'E_25_1-6_1',
 'E_25_2-6_2',
 'E_25_3-6_3']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM