Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to partition a list with N partitions rather than partitions of size N?

Guava's method, Lists#partition, partitions a List<?> into a List<List<?>> where each partition contains N elements (as specified by the second parameters of the function, and excluding the last partition).

Is it possible to use this method but create N partitions instead?

If not, what are some ways to go about it?

I've attempted to create 31 partitions with the following (keys is a List<String> of size 57), but it only creates 29:

List<String> keys = ...;

var paritions = Lists.partition(keys, (int) Math.ceil(keys.size() / 31D));
like image 530
Jacob G. Avatar asked Sep 08 '25 01:09

Jacob G.


2 Answers

The problem is that your customized partitioning distributes the "empty space" (i.e. gaps left by a lack of elements to fully fill the partitions) differently than Guava's method. That method will fill each partition completely before creating the next, while you want to evenly distribute the elements. This is because partition() defines the size of the groups, while you want to specify the number of groups.

Look at this custom implementation:

private static <T> List<List<T>> distribute(List<T> elements, int nrOfGroups)
{
    int elementsPerGroup = elements.size() / nrOfGroups;
    int leftoverElements = elements.size() % nrOfGroups;

    List<List<T>> groups = new ArrayList<>();
    for (int i = 0; i < nrOfGroups; i++)
    {
        groups.add(elements.subList(i * elementsPerGroup + Math.min(i, leftoverElements),
                                    (i + 1) * elementsPerGroup + Math.min(i + 1, leftoverElements)));
    }
    return groups;
}

It will calculate the minimum size of the groups (floor of count/#groups) and then correct that for the first few groups in case there are elements left.

Example

List<Integer> elements = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
int nrOfGroups = 6;
// [[1, 2], [3, 4], [5], [6], [7], [8]]
like image 127
Malte Hartwig Avatar answered Sep 09 '25 17:09

Malte Hartwig


To be able to create N partitions, you have to have a minimum of 2N elements. In your case, you have a partition requirement of 31, which means you'd need 62 elements.

Because you have 57 elements, you're five elements - or two and a half partitions - short of the required minimum, which is why you get 29 partitions, with the last partition only having one element.

Guava is doing its job. You don't have enough elements to properly subdivide into the partitions you want.

like image 29
Makoto Avatar answered Sep 09 '25 17:09

Makoto