Source code for s3manifesto.grouper

# -*- coding: utf-8 -*-

import typing as T
from collections import deque

from .typehint import T_FILE_SPEC


[docs]def group_files( files: T.List[T_FILE_SPEC], target: int, sort_by_target: bool = True, ) -> T.List[T.Tuple[T.List[T_FILE_SPEC], int]]: """ Given a list of :class:`File` and a target size, put them into groups, so that each group has approximately the same size as the target size. :param files: List of files to be grouped :param target: Target size or target n_record for each group """ half_target_size = target // 2 if sort_by_target: files = deque(sorted(files, key=lambda x: [1])) else: # pragma: no cover files = deque(files) file_groups = list() file_group = list() file_group_size = 0 while 1: # if no files left if len(files) == 0: if len(file_group): file_groups.append((file_group, file_group_size)) break remaining_size = half_target_size - file_group_size # take the largest file if remaining_size <= half_target_size: file = files.popleft() # take the smallest file else: file = files.pop() file_group.append(file) file_group_size += file[1] if file_group_size >= target: file_groups.append((file_group, file_group_size)) file_group = list() file_group_size = 0 return file_groups