-2

I want to convert a list like this: L = ['ad', 'bc', 'gh', 'kj', 'ws', 'er', 'th']

into [('ad', 'bc', 'gh', 'kj', 'ws'), ('er', 'th', None, None, None)] using python 3

The tuples will contain the equal amount of elements even if the list doesn't provide enough elements. So if i have 6 elements, i will get two tuples, one full of 5 elements and the other will have only one element and 4 Nones. But if i have only 5 elements i should get a list of one tuple containing 5 elements.

i tried zip but it doesn't give me the desired result

Mido H
  • 51
  • 7
  • 3
    Please update your question with the code you have tried. – quamrana Jul 31 '22 at 16:46
  • 1
    Do you always need 2 tuples? Is the first one only containing 5 elements? The question is not really clear – mauro Jul 31 '22 at 16:51
  • 1
    no, not just two tuples, i want it to keep going for as many elements the list will contain. So if i have 100 elements, each tuple should contain 5 elements only, but if the elements amount cannot be divided to give 5 for each, then i want it to be covered up by None values. – Mido H Jul 31 '22 at 16:54

3 Answers3

0

You can use grouper from the more_itertools package for this:

from more_itertools import grouper

l = ['ad', 'bc', 'gh', 'kj', 'ws', 'er', 'th']
result = list(grouper(l, 5, incomplete="fill", fillvalue=None))
print(result)

gives

[('ad', 'bc', 'gh', 'kj', 'ws'), ('er', 'th', None, None, None)]

Alternatively, as Tomerikoo points out, you can construct the grouper function using itertools in the standard library:

from itertools import zip_longest

def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
    "Collect data into non-overlapping fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
    # grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
    # grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
    args = [iter(iterable)] * n
    if incomplete == 'fill':
        return zip_longest(*args, fillvalue=fillvalue)
    if incomplete == 'strict':
        return zip(*args, strict=True)
    if incomplete == 'ignore':
        return zip(*args)
    else:
        raise ValueError('Expected fill, strict, or ignore')
MattDMo
  • 100,794
  • 21
  • 241
  • 231
  • There is also the [`grouper` recipe](https://docs.python.org/3.7/library/itertools.html#itertools-recipes) from the built-in `itertools` which is just a two lines function – Tomerikoo Aug 01 '22 at 05:36
  • @Tomerikoo thanks, I've put that in the answer. To be pedantic, it is a 9-line function, not two, although you could compress it to 5 :P – MattDMo Aug 01 '22 at 21:52
0

Python code:

def getTuples(size):
    intSize = size // 5
    if size / 5 > intSize:
        return (intSize + 1) * 5
    else:
        return intSize * 5
def convert(l):
    new = []
    t = ()
    tValue = 0

    for i in range(0, getTuples(len(l))):
        tValue += 1
        try:
            val = l[i]
        except IndexError:
            val = None
        if tValue == 5:
            new.append(t)
            t = ()
        else:
            t = t + (val,)
     new.append(t)
0
L = ['ad', 'bc', 'gh', 'kj', 'ws', 'er', 'th']

L3 = list()
idx = 0

while idx < len(L):

    L2 = list()
    for idx2 in range(5):
         L2.append(L[idx])
         idx = idx +1
         if idx >= len(L):
             break
    while idx2 < 4:
        L2.append(None)
        idx2 = idx2 + 1
    L3.append(tuple(L2))
print(L3)

    
Robert Jacobs
  • 3,266
  • 1
  • 20
  • 30