将数据集分成n个分区

Divide dataset into n partition

假设我有一个数组a。我想把它分成 n 个分区。如何在 Java 中执行 for 函数?我试过这段代码,但在某些情况下是错误的。

public static void main(String[] args) {
        int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int[] part = {0, 1, 2, 3};
        for (int i = 0; i < part.length; i++) {
            for (int j = ((a.length / part.length) * part[i]); j < ((a.length / part.length) * (part[i] + 1)); j++) {
                System.out.print(a[j] + " ");
            }
            System.out.println();
        }
    }
}

输出:

1 2 
3 4 
5 6 
7 8

数据 9 和 10 丢失。我不需要相同的大小,但至少所有数据都分布良好。如何修改for j函数?

这是一种可能的解决方案(非常幼稚的方法,未针对性能进行基准测试或优化):

int numOfPartitions = 4; 
double n = (double)a.length/numOfPartitions;
int start =0;
int partitionNum=1;
while(partitionNum<= numOfPartitions)
  {        
    int end = (int)java.lang.Math.ceil(n*partitionNum);
    for(int k = start;k<end;k++)
      {
        System.out.print(a[k] + " ");
      }
    start = end;
    ++partitionNum;
    System.out.println();
  }

首先,查看每个分区的大小(即使不是整数)。我们将使用它将数组分割成子数组。

现在,开始从输入数组的第一个元素切入子数组。我们采用的策略是取最接近(计算出的分区大小*当前分区数)的最大整数作为上界。在这个例子中,我们有 size = 10/4 = 2.5,所以我们分解成子数组的索引将是 3(对于 2.5)、5、8(对于 7.5)和 10。

第一个子数组将采用从输入的索引 0 到索引 2 的元素,因为第一个计算的索引是 3。下一个子数组从索引 3 开始,一直到索引 5,依此类推。

这样,我们最终得到元素数量最多相差 1 的子数组。

注意:如果我们的分区多于输入中元素的数量,我们可以 return 整个数组。

Guava's Lists.partition():

List<Integer> longList = Arrays.asList(1, 2, 3, 4, 5);

List<List<Integer>> lists = Lists.partition(longList, 2);
lists.forEach(System.out::println);

输出:

[1, 2]
[3, 4]
[5]