1

I am trying to split my list into a dictionary and I wrote a function for it. It takes in a list and gets the list length. If the length of the list is 253 , it creates a dictionary with 26 keys - this is calculated by rounding up the number to a higher 10 (250 will create 25 keys, 251-259 will create 26 keys). Each key will store a chuck of the original list (as of now I am storing 10 elements per list). I feel

def limit_files(file_list, at_a_time=10):

    l = file_list
    n = len(l)
    d, r = divmod(n, at_a_time) 

    num_keys = d + 1 if r else d   
    slice = n // num_keys
    vals = (l[i:i+slice] for i in range(0, n, slice+1)) 
    dct = dict(zip(range(1,num_keys+1),vals))
    return (dct)

I just wanted to know if there is way to improve the code

letsc
  • 2,515
  • 5
  • 35
  • 54
  • 2
    In this case, you don't get anything from having a dict of lists since the keys are all integers... A list of lists seems more natural. In that case, this becomes a dupe of http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python – mgilson Feb 19 '15 at 06:13
  • I want to iterate over the chunks. Generators will not allow that – letsc Feb 19 '15 at 06:42

1 Answers1

4

You can use itertools.izip_longest to group items in your list as equally divided chunks.

import itertools

def limit_files(file_list, at_a_time=10):
    d, r = divmod(len(file_list), at_a_time)
    num_keys = d + 1 if r > 0 else d 

    chunks = itertools.izip_longest(*([iter(x)] * at_a_time))
    return dict((x, y) for x, y in enumerate(chunks))

Note that, it will be padding with None values to fill out the last chunk.

>>> limit_files([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
{0: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
 1: (11, 12, None, None, None, None, None, None, None, None)} 

Alternatively, without using padding values, you can just iterate through the range and call itertools.islice until the iterator exhausts as follows:

def limit_files(file_list, at_a_time=10):
    d, r = divmod(len(file_list), at_a_time)
    num_keys = d + 1 if r > 0 else d 

    iterator = iter(file_list)
    dictionary = {}
    for chunk_id in xrange(num_keys):
        chunk = list(itertools.islice(iterator, at_a_time))
        if not chunk:
            break
        dictionary[chunk_id] = chunk
    return dictionary

>>> limit_files([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
{0: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 1: [11, 12]}
Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119