0

Problem:

I want to make a list of lists with a sub list string count of three. I tried it with technics for matrixes but so far it won't work.

I couldn't get it to count, create list, first element, second element, third element, create new list, insert fourth element, fifth element, sixth element, create new list...

It would be nice if the code would also work with a list length of items that can't be divided by 3. So like 8 strings in my source list.

Sample Data:

my_list = ['Item11', 'Item12', 'Item13', 'Item24', 'Item25', 'Item26', 'Item37', 'Item38', 'Item39']

What I've tried:

sublist = []
for mainlist in range(3):
    # Append an empty sublist inside the list
    mainlist.append([])
    for item in my_list:
        for sublist in mainlist:
            sublist.append(item)

print(sublist)

Expected result:

my_list = [['Item11', 'Item12', 'Item13'], ['Item24', 'Item25', 'Item26'], ['Item37', 'Item38', 'Item39']]
BenjaminK
  • 653
  • 1
  • 9
  • 26
  • This seems to require more explanation: the strings in your output list do not match the ones in the input. However, there's nothing in your code to effect that change. – Prune May 12 '20 at 22:33
  • @Prune I'm sorry I updated the result. I typed it wrong, now it should match. – BenjaminK May 12 '20 at 22:34
  • 1
    This seems to be a duplicate -- but you have to know that this is called "chunking" a list. Search for "Python chunk list". – Prune May 12 '20 at 22:35
  • I'm currently looking it up. Never heard the term "chunking" Thanks so far. I keep you posted. – BenjaminK May 12 '20 at 22:37
  • No kidding ... it's not a formal Python term, just what data manglers call the process. – Prune May 12 '20 at 22:42

2 Answers2

1

It's called "yield chunks" and there is a thread I found after being told what the term is.

List to Stackoverflow solutions to chunck a list

def chunks(lst, n):
    """Yield successive n-sized chunks from lst."""
    for i in range(0, len(lst), n):
        yield lst[i:i + n]


print(list(chunks(my_list, 3)))

A second solution with itertools:

#from itertools import izip_longest as zip_longest # for Python 2.x
from itertools import zip_longest # for Python 3.x
#from six.moves import zip_longest # for both (uses the six compat library)

def grouper(n, iterable, padvalue=None):
    "grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
    return zip_longest(*[iter(iterable)]*n, fillvalue=padvalue)

print(grouper(3, my_list)))
BenjaminK
  • 653
  • 1
  • 9
  • 26
  • After linking to the page you did, if you decided to quote some of the code there, why not the simplest one, based on list comprehension. I suggest you include that as the top solution (possibly only solution) that you quote. – Amitai Irron May 12 '20 at 23:06
1

I think that's what you're looking for (works aswell if the number of items in my_list is not divisible by 3):

my_list = ['Item11', 'Item12', 'Item13', 'Item24', 'Item25', 'Item26', 'Item37', 'Item38', 'Item39']

mainlist = []
if len(my_list) < 3:
    mainlist.append(my_list)
else:
    # The magic is here
    first_items = my_list[::3]
    second_items = my_list[1::3]
    third_items = my_list[2::3]

    for i in range(len(third_items)):
        temp_list = [first_items[i], second_items[i], third_items[i]]
        mainlist.append(temp_list)

    # This if is for when the number of items are not divisible by 3
    if len(second_items) > len(third_items):
        if len(first_items) > len(second_items):
            mainlist.append([first_items[-1]])
        else:
            mainlist.append([first_items[-1], second_items[-1]])

print(mainlist)
  • Thanks, it's an interesting solution. I'm taking a closer look at how you structured it! – BenjaminK May 12 '20 at 22:50
  • 1
    It is an interesting solution, but overly complex relative to the one-liner: `[lst[i:i + n] for i in range(0, len(lst), n)]` (part of the page linked to by @BenjaminK`s answer) – Amitai Irron May 12 '20 at 23:04
  • @DanielLavedoniodeLima can you please explain [::3] in your solution. Thank you – BenjaminK May 13 '20 at 00:37
  • 1
    @BenjaminK sure. So this is known in Python as "slicing". There's a great explanation already here in [StackOverflow](https://stackoverflow.com/a/509295/11981524) and a (not as good) in the [official Python tutorial](https://docs.python.org/3.8/tutorial/introduction.html#lists). – Daniel Lavedonio de Lima May 13 '20 at 00:55