Shona
Shona

Reputation: 261

python list within list - why is the sublist repeated

Problem: Create an list from a given a string of numbers from 1-9 and such that every number in the string is inserted into the mainlist and every following smaller number will be inserted into a sublist until finding a greater number than the preceding which then will be inserted onto the normal(main) list and continue.

question: ex. string = '654976' expected result = [6,[5,4],9,[7,6]] actual = [6,[5,4],[5,4],9,[7,6],[7,6]] <= why is sublist is repeated?

def create_inner_list(string):
    mainlist = []
    prev = 0
    sublist = []
    if len(string) <= 1
        return mainlist.append(string)
    for each in string:
        if int(each) <= prev:
            prev = int(each)
            sublist.append(int(each))
            print(sublist)
            mainlist.append(sublist)
            print(mainlist)
            continue
        sublist = []
        mainlist.append(int(each))
        prev = int(each)
    return mainlist

I also did try to use a split method on the string but it didn't help much, or didn't exactly understand how to use it. Hope it is clear. Thanks in advance.

Upvotes: 1

Views: 82

Answers (5)

Pynchia
Pynchia

Reputation: 11606

Here's another solution using itertools.groupby and "static" variables

import itertools as it

def group_f(value):
    value = int(value)
    if not hasattr(group_f, 'prev'):
        group_f.prev = 0
        group_f.g = False
    if value > group_f.prev:
        group_f.g = not group_f.g
    group_f.prev = value
    return group_f.g

def create_inner_list(s):
    res = []
    for _, values in it.groupby(s, group_f):
        res.append(next(values))
        res.append(list(values))
    return res

print(create_inner_list('654976'))

which produces

['6', ['5', '4'], '9', ['7', '6']]

Basically, group_f returns an alternating sequence of True/False upon every subsequence.

groupby uses it to group the original input values into groups, therefore splitting the input sequence into subsequences.

create_inner_list uses those to form a new list, appending the first element of each group and the remaining elements as a list.

Upvotes: 1

marian0
marian0

Reputation: 654

The reason you are seeing each sublist twice is because your are adding the sublist to the mainlist each time you find an element that is lower than the previous one.

def create_inner_list(string):
    mainlist = []
    prev = 0
    sublist = []
    if len(string) <= 1
        return mainlist.append(string)
    for each in string:
        if int(each) <= prev:
            prev = int(each)
            sublist.append(int(each))
            print(sublist)            <----- This code is executed once
            mainlist.append(sublist)  <-----  for each element you are 
            print(mainlist)           <-----  adding to the sublist
            continue
        sublist = []
        mainlist.append(int(each))
        prev = int(each)
    return mainlist

Also, after the for loop you should check if there is a non-empty sublist that has not been apended to the mainlist.

Try with this instead:

def create_inner_list(string):
    mainlist = []
    prev = 0
    sublist = []
    if len(string) <= 1:
        return mainlist.append(string)
    for each in string:
        if int(each) <= prev:
            prev = int(each)
            sublist.append(int(each))
            continue
        if len(sublist) > 0:
            mainlist.append(sublist)
            sublist = []
        mainlist.append(int(each))
        prev = int(each)
        print(mainlist)
    if len(sublist) > 0:
        mainlist.append(sublist)
        sublist = []
        print(mainlist)
    return mainlist

Upvotes: 1

Maor2871
Maor2871

Reputation: 147

How about this?:

def create_inner_list(string1):

    main_list = []

    for i in range(0, len(string1), 3):

        main_list.append(string1[i])

        if len(string1) - i == 2:
            main_list.append(string1[i+1])

        elif len(string1) - i == 1:
            break

        else:
            main_list.append(list(string1[i+1] + string1[i+2]))

    return main_list

def main():

    string2 = '714683241390'
    print create_inner_list(string2)

main()

Upvotes: 0

Daniel
Daniel

Reputation: 42788

You're appending sublist for each number in sublist once. You have to move the append(sublist) outside the if:

def create_inner_list(string):
    prev = 0
    mainlist = []
    sublist = []
    for each in string:
        if int(each) <= prev:
            prev = int(each)
            sublist.append(int(each))
        else:
            if sublist:
                mainlist.append(sublist)
            sublist = []
            mainlist.append(int(each))
            prev = int(each)
    if sublist:
        mainlist.append(sublist)
    return mainlist

or a bit more sophisticated:

def create_inner_list(string):
    prev = 0
    current_list = mainlist = []
    for each in string:
        if int(each) <= prev:
            if current_list is mainlist:
                current_list = []
                mainlist.append(current_list)
        else:
            current_list = mainlist
        prev = int(each)
        current_list.append(prev)
    return mainlist

Upvotes: 2

Martin Konecny
Martin Konecny

Reputation: 59701

It's because of your continue statement.

After each iteration of

for each in string:

You expect your sublist to be reinitialized with the code

sublist = []

But with your continue statement, you are skipping that step (and so you are adding the same list a second time on the next iteration). Make sure you reinitialize your sublist at the beginning of each loop:

for each in string:
    sublist = []
    ...

Upvotes: 1

Related Questions