-1

I'd like to split an array into n roughly equal sized chunks, without knowing how large these chunks will be beforehand.

Using Numpy, this can be done with array_split:

>>> import numpy >>> x = [7, 3, 9, 10, 5, 6, 8, 13] >>> x [7, 3, 9, 10, 5, 6, 8, 13] >>> numpy.array_split(x, 3) [array([7, 3, 9]), array([10, 5, 6]), array([ 8, 13])] 

What's the Java equivalent of doing this? I'm happy to use a library function if available.

7
  • Have you looked it up? A quick search gives you tons of examples and some also mention Guava's Lists.partition Commented Nov 6, 2022 at 11:48
  • Perhaps this helps you stackoverflow.com/questions/27857011/… Commented Nov 6, 2022 at 11:50
  • @QBrute Of course, and I'm surprised Lists.partitions hasn't shown up so far. Commented Nov 6, 2022 at 11:52
  • @office.aizaz The problem with this approach is, that it needs me to know the chunksize before hand. Commented Nov 6, 2022 at 11:53
  • @TMOTTM you know, if you have number of chunks you can calculate chunk size from list size Commented Nov 6, 2022 at 11:59

2 Answers 2

0

If it helps anyone.

@Test public void testListPartition() { // Given Integer[] is = new Integer[] {7, 3, 9, 10, 5, 6, 8, 13}; List<Integer> isList = new ArrayList<Integer>(); Collections.addAll(isList, is); int nThreads = 3; int sizeSublist = (int) Math.ceil(isList.size()/(double)nThreads); List<Integer> truthOne = new ArrayList<Integer>(); Collections.addAll(truthOne, new Integer[] {7, 3, 9}); List<Integer> truthTwo = new ArrayList<Integer>(); Collections.addAll(truthTwo, new Integer[] {10, 5, 6}); List<Integer> truthThree = new ArrayList<Integer>(); Collections.addAll(truthThree, new Integer[] {8, 13}); // When List<List<Integer>> partitions = Lists.partition(isList, sizeSublist); // Then assertEquals(truthOne, partitions.get(0)); assertEquals(truthTwo, partitions.get(1)); assertEquals(truthThree, partitions.get(2)); } 
Sign up to request clarification or add additional context in comments.

Comments

0

You can split the list using Stream.

static <T> List<List<T>> splitList(List<T> list, int n) { int size = list.size(); return IntStream.range(0, (size + n - 1) / n) .map(i -> n * i) .mapToObj(i -> list.subList(i, Math.min(i + n, size))) .collect(Collectors.toList()); } 

Note that since this uses subList(), each split list shares the original list.

You can split the array as well.

@SuppressWarnings("unchecked") static <T> T[][] splitArray(T[] array, int n) { int size = array.length; return IntStream.range(0, (size + n - 1) / n) .map(i -> n * i) .mapToObj(i -> Arrays.copyOfRange(array, i, Math.min(i + n, size))) .toArray(i -> (T[][])Array.newInstance(array.getClass(), n)); } 

However, this cannot be applied to arrays of primitive types.

Separate implementations are required for primitive types.

For example, for int array:

static int[][] splitArray(int[] array, int n) { int size = array.length; return IntStream.range(0, (size + n - 1) / n) .map(i -> n * i) .mapToObj(i -> Arrays.copyOfRange(array, i, Math.min(i + n, size))) .toArray(int[][]::new); } 

test:

public static void main(String[] args) { List<Integer> list = List.of(7, 3, 9, 10, 5, 6, 8, 13); System.out.println(splitList(list, 3)); Integer[] array = {7, 3, 9, 10, 5, 6, 8, 13}; System.out.println(Arrays.deepToString(splitArray(array, 3))); int[] ints = {7, 3, 9, 10, 5, 6, 8, 13}; System.out.println(Arrays.deepToString(splitArray(ints, 3))); } 

output:

[[7, 3, 9], [10, 5, 6], [8, 13]] [[7, 3, 9], [10, 5, 6], [8, 13]] [[7, 3, 9], [10, 5, 6], [8, 13]] 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.