P3.5: Creating Sublist

85 views Asked by At

I have this code:

    all_jobids = ['270', '271', '274', '278', '|_279', '|_280', '|_281', '288', '289', '|_290', '|_291', '298',
                  '299', '|_300', '|_301', '|_302', '|_303', '308']

    intjobs = []
    for entry in all_jobids:
        sub_id = 0
        try:
            current_id = int(entry)
            intjobs.append(current_id)
        # except ValueError:
        #     sub_id = int(entry[2:])
        #     last_id = intjobs[-1]
        #     intjobs[-1] = [last_id].append(sub_id)
        except ValueError:
            sub_id = int(entry[2:])

            if intjobs[-1] is list:
                intjobs[-1].append(sub_id)
            else:
                last_id = intjobs[-1]
                intjobs[-1] = [last_id].append(sub_id)

            # intjobs[last_id] = [last_id].append(int(current_id[2:]))
        print(entry, current_id, sub_id)

        last_id = current_id
    print(intjobs)

and have this output:

[270, 271, 274, None, 288, None, 298, None, 308]

but I want this (dots are just for shorter display):

[270, 271, 274, [278, ..., 281], 288, [289, 290, 291], 298, [299, ..., 303], 308]

So what I want is a list with optional sublists. I already looked after other Q&A (e.q. Make Python Sublists from a list using a Separator but it's not the same.

4

There are 4 answers

0
ettanany On

Using try .. except to catch ValueError exceptions, you can get the desired output like below:

int_jobids = []

for i in all_jobids:
    try:
        int_jobids.append(int(i))
        if sub_list:  # We use sub_list for items that start with '|_'
            sub_list.insert(0, int_jobids.pop(-2))
            int_jobids.insert(-1, sub_list[:])
            sub_list = []
    except ValueError:
        sub_list.append(int(i[2:]))

Output:

>>> int_jobids
[270, 271, 274, [278, 279, 280, 281], 288, [289, 290, 291], 298, [299, 300, 301, 302, 303], 308]
2
Robin Koch On

A one-line solution (because: python) is:

[[int(id) for id in sublist.split('|')] if '|' in sublist else int(sublist) for sublist in ";".join(all_jobids).replace(';|_', '|').split(';')]

Explanation:

";".join(all_jobids)

Concats all IDs by a semicolon (or separator1).

.replace(';|_', '|')

Removes the semicolon where sublists are desired and replaces them with a bar (or separator2).

.split(';')

Splits the string up in IDs and concatenated sub lists.

[[[int(id) for id in sublist.split('|')] if '|' in sublist else int(sublist) for sublist in ... ]

Takes the entrys and splits them at the bar (or separator2) if there is one. IDs with no bar stay untouched. (Except casting.)

Output:

[270, 271, 274, [278, 279, 280, 281], 288, [289, 290, 291], 298, [299, 300, 301, 302, 303], 308]

Maybe for further processing it's desired, that the single IDs are lists, too. In that case the simple statement would be:

[[int(id) for id in sublist.split('|')] for sublist in ";".join(all_jobids).replace(';|_', '|').split(';')]

Output:

[[270], [271], [274], [278, 279, 280, 281], [288], [289, 290, 291], [298], [299, 300, 301, 302, 303], [308]]
0
Mike Müller On

This works:

all_jobids = ['270', '271', '274', '278', '|_279', '|_280', '|_281', '288', '289', '|_290', '|_291', '298',
                  '299', '|_300', '|_301', '|_302', '|_303', '308']
intjobs = []
in_sub = False
for entry in all_jobids:
    if entry.startswith('|_'):
        entry = int(entry[2:])
        if not in_sub:
            sub = [intjobs[-1], entry]
            intjobs[-1] = sub
            in_sub = True
        else:
            sub.append(entry)
    else:
        in_sub = False
        intjobs.append(int(entry))
print(intjobs)

Output:

[270,
 271,
 274,
 [278, 279, 280, 281],
 288,
 [289, 290, 291],
 298,
 [299, 300, 301, 302, 303],
 308]
1
Maarten Fabré On

This might not be the most elegant solution, but it works.

This creates a smaller list sublist which gets reset every time a 'normal' item gets added.

all_jobids = ['270', '271', '274', '278', '|_279', '|_280', '|_281', '288', '289', '|_290', '|_291', '298',
              '299', '|_300', '|_301', '|_302', '|_303', '308']
intjobs = []
sublist = []
current_id = None
for entry in all_jobids:
    try:
        last_id = current_id
        current_id = int(entry)
        if sublist:
            intjobs.append(sublist)
            last_id = sublist
            sublist = []
        elif last_id:
            intjobs.append(last_id)
        # intjobs.append(current_id)

    except ValueError:
        sub_id = int(entry[2:])
        # sublist.append(sub_id)
        if sublist:
            sublist.append(sub_id)
        else:
            sublist.append(last_id)
            sublist.append(sub_id)

    # print(entry, current_id, sub_id)
if sublist: #if the last item was a sublist item
    intjobs.append(sublist)
else:
    intjobs.append(current_id)

print(intjobs)

returns

[270, 271, 274, [278, 279, 280, 281], 288, [289, 290, 291], 298, [299, 300, 301, 302, 303], 308]