将数组分割成X长度的部分

时间:2022-01-22 21:39:33

Currently I have an array of size N. I'm trying to copy every X amount of bytes from the array.

目前我有一个大小为n的数组,我正在尝试从数组中复制每X个字节。

Example if the array is size 10 and I want arrays of size 3. I'd copy the first 3 elements then the next 3 and the last 1.

例如,如果数组是10,而我要的是3号数组。复制前3个元素,然后是下3个,最后1个。

Currently I'm using the following algorithm:

目前我使用的算法如下:

int I = 0;
int sub = bytes.length;
int counter = 0;
for (I = 0; I < bytes.length; ++I) {
    if (I % 3 == 0 && I != 0) {
       NewArray[counter] = Arrays.copyOfRange(bytes, I - 3, I));
        sub -= 3;
        ++counter;
    }
}

NewArray[counter] = Arrays.copyOfRange(bytes, I - sub, I)); //Copy remainder.

Is there a more efficient or a more decent way of doing the what I want? This algorithm looks pretty bad =l

有没有一种更有效或更体面的方式去做我想做的事?这个算法看起来很糟糕=l

Any ideas how I can improve it or at least a hint?

有什么办法可以改进它或者至少是一个提示吗?

8 个解决方案

#1


10  

What about this:

这个:

int x = 3;  // chunk size
int len = bytes.length;
int counter = 0;

for (int i = 0; i < len - x + 1; i += x)
    newArray[counter++] = Arrays.copyOfRange(bytes, i, i + x);

if (len % x != 0)
    newArray[counter] = Arrays.copyOfRange(bytes, len - len % x, len);

#2


6  

Here's a convenient method that converts a byte[] to an array of byte[]'s. So, the result is a byte[][].

这里有一个方便的方法,可以将一个字节[]转换为一个字节[]s的数组。结果是一个字节[][][]。

public byte[][] splitBytes(final byte[] data, final int chunkSize)
{
  final int length = data.length;
  final byte[][] dest = new byte[(length + chunkSize - 1)/chunkSize][];
  int destIndex = 0;
  int stopIndex = 0;

  for (int startIndex = 0; startIndex + chunkSize <= length; startIndex += chunkSize)
  {
    stopIndex += chunkSize;
    dest[destIndex++] = Arrays.copyOfRange(data, startIndex, stopIndex);
  }

  if (stopIndex < length)
    dest[destIndex] = Arrays.copyOfRange(data, stopIndex, length);

  return dest;
}

Some advantages compared to the previous best answer:

与之前的最佳答案相比,有一些优势:

  1. The for condition uses a <= which makes more sense than < ... + 1.
  2. for条件使用的<=比<…更有意义+ 1。
  3. Putting the stop-index in a temporary field reduces the number of calculations in the last if block.
  4. 将停止索引放在临时字段中会减少最后一个if块中的计算数量。

(Unit tested)

(单元测试)

#3


3  

Few things to do here:

这里很少有事情可做:

First, common conventions frown apon using capitals to start variable names, change the I and NewArray variables to 'i' and 'newArray' respectively.

首先,常见的惯例是使用大写字母来启动变量名,将I和NewArray变量分别改为“I”和“NewArray”。

Then, your code does not work because your first time through the loop, i-3 will lead to an IndexOutOfBounds exception.....

那么,您的代码就不能工作了,因为您第一次通过循环,i-3将导致IndexOutOfBounds异常……

Finally, you do not show how you set the size of the newArray array.

最后,您没有显示如何设置newArray数组的大小。

int sublen = 3; // how many elements in each sub array.
int size = ((bytes.length - 1) / sublen) + 1; // how many newArray members we will need
byte[][] newArray = new byte[size][]; 
int to = byte.length;
int cursor = size - 1;
int from = cursor * sublen;
while (cursor >= 0) {
    newArray[cursor] = Arrays.copyOfRange(bytes, from, to);
    to = from;
    from -= sublen;
    cursor --;
}

#4


2  

Here's my implementation for this, it will split your array in sub-arrays of up to a maximum size you decide on, and put the sub-arrays into a list of arrays. The last array will be smaller if the size of the array is not a multiple of the maximum size chosen.

这里是我的实现,它将把数组分成几个子数组,以最大大小来决定,然后将子数组放入数组列表中。如果数组的大小不是所选择的最大大小的倍数,那么最后一个数组将会更小。

import java.util.Arrays;
...

public static <T> List<T[]> splitArray(T[] items, int maxSubArraySize) {
  List<T[]> result = new ArrayList<T[]>();
  if (items ==null || items.length == 0) {
      return result;
  }

  int from = 0;
  int to = 0;
  int slicedItems = 0;
  while (slicedItems < items.length) {
      to = from + Math.min(maxSubArraySize, items.length - to);
      T[] slice = Arrays.copyOfRange(items, from, to);
      result.add(slice);
      slicedItems += slice.length;
      from = to;
  }
  return result;
}

#5


0  

You can use split with a special regular expression:

你可以使用分割和一个特殊的正则表达式:

 System.out.println(Arrays.toString(
     "Thisismystringiwanttosplitintogroupswith4chareach".split("(?<=\\G.{4})")
 ));

Credit to earlier post by Alan Moore. Please visit and vote up.

由艾伦·摩尔(Alan Moore)早些时候发表的文章。请访问并投票。

#6


0  

If actually you need quite big chunks, and don't want to modify their contents independently, consider reusing the same initial array by means of ByteBuffer.wrap() and then slice() repeatedly. This would prevent unnecessary copying and memory waste.

如果实际上您需要相当大的块,并且不想独立地修改它们的内容,可以考虑使用ByteBuffer.wrap()和slice()来重用相同的初始数组。这将防止不必要的复制和内存浪费。

#7


0  

Here is a function to split arrays, you can use below main method to test it.

这是一个分割数组的函数,您可以使用下面的main方法来测试它。

private static List<Integer[]> splitArray(Integer[] originalArray, int chunkSize) {
List<Integer[]> listOfArrays = new ArrayList<Integer[]>();
int totalSize = originalArray.length;
if(totalSize < chunkSize ){
   chunkSize = totalSize;
}
int from = 0;
int to = chunkSize;

while(from < totalSize){
    Integer[] partArray = Arrays.copyOfRange(originalArray, from, to);
    listOfArrays.add(partArray);

    from+= chunkSize;
    to = from + chunkSize;
    if(to>totalSize){
        to = totalSize;
    }
}
return listOfArrays;
}

Testing method:

测试方法:

public static void main(String[] args) {
List<Integer> testingOriginalList = new ArrayList<Integer>();

for(int i=0;i<200;i++){
    testingOriginalList.add(i);
}

int batchSize = 51;
Integer[] originalArray = testingOriginalList.toArray(new Integer[]{});

List<Integer[]> listOfArrays = splitArray(originalArray, batchSize);


for(Integer[] array : listOfArrays){
    System.out.print(array.length + ", ");
    System.out.println(Arrays.toString(array));
}
}

#8


0  

import java.util.Arrays;

public class Test {

    private void run() {
        try {

            byte[] cfsObjIds = "abcdefghij".getBytes();
            System.out.println(Arrays.toString(cfsObjIds));

            final int chunkSize = 4;
            System.out.println("Split by " + chunkSize + ":");
            int objQty = cfsObjIds.length;
            for (int i = 0; i < objQty; i += chunkSize) {
                int chunkUpperLimit = Math.min(objQty, i + chunkSize);
                byte[] cfsIdsChunk = Arrays.copyOfRange(cfsObjIds, i, chunkUpperLimit);

                System.out.println(Arrays.toString(cfsIdsChunk));
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        new Test().run();
    }
}

#1


10  

What about this:

这个:

int x = 3;  // chunk size
int len = bytes.length;
int counter = 0;

for (int i = 0; i < len - x + 1; i += x)
    newArray[counter++] = Arrays.copyOfRange(bytes, i, i + x);

if (len % x != 0)
    newArray[counter] = Arrays.copyOfRange(bytes, len - len % x, len);

#2


6  

Here's a convenient method that converts a byte[] to an array of byte[]'s. So, the result is a byte[][].

这里有一个方便的方法,可以将一个字节[]转换为一个字节[]s的数组。结果是一个字节[][][]。

public byte[][] splitBytes(final byte[] data, final int chunkSize)
{
  final int length = data.length;
  final byte[][] dest = new byte[(length + chunkSize - 1)/chunkSize][];
  int destIndex = 0;
  int stopIndex = 0;

  for (int startIndex = 0; startIndex + chunkSize <= length; startIndex += chunkSize)
  {
    stopIndex += chunkSize;
    dest[destIndex++] = Arrays.copyOfRange(data, startIndex, stopIndex);
  }

  if (stopIndex < length)
    dest[destIndex] = Arrays.copyOfRange(data, stopIndex, length);

  return dest;
}

Some advantages compared to the previous best answer:

与之前的最佳答案相比,有一些优势:

  1. The for condition uses a <= which makes more sense than < ... + 1.
  2. for条件使用的<=比<…更有意义+ 1。
  3. Putting the stop-index in a temporary field reduces the number of calculations in the last if block.
  4. 将停止索引放在临时字段中会减少最后一个if块中的计算数量。

(Unit tested)

(单元测试)

#3


3  

Few things to do here:

这里很少有事情可做:

First, common conventions frown apon using capitals to start variable names, change the I and NewArray variables to 'i' and 'newArray' respectively.

首先,常见的惯例是使用大写字母来启动变量名,将I和NewArray变量分别改为“I”和“NewArray”。

Then, your code does not work because your first time through the loop, i-3 will lead to an IndexOutOfBounds exception.....

那么,您的代码就不能工作了,因为您第一次通过循环,i-3将导致IndexOutOfBounds异常……

Finally, you do not show how you set the size of the newArray array.

最后,您没有显示如何设置newArray数组的大小。

int sublen = 3; // how many elements in each sub array.
int size = ((bytes.length - 1) / sublen) + 1; // how many newArray members we will need
byte[][] newArray = new byte[size][]; 
int to = byte.length;
int cursor = size - 1;
int from = cursor * sublen;
while (cursor >= 0) {
    newArray[cursor] = Arrays.copyOfRange(bytes, from, to);
    to = from;
    from -= sublen;
    cursor --;
}

#4


2  

Here's my implementation for this, it will split your array in sub-arrays of up to a maximum size you decide on, and put the sub-arrays into a list of arrays. The last array will be smaller if the size of the array is not a multiple of the maximum size chosen.

这里是我的实现,它将把数组分成几个子数组,以最大大小来决定,然后将子数组放入数组列表中。如果数组的大小不是所选择的最大大小的倍数,那么最后一个数组将会更小。

import java.util.Arrays;
...

public static <T> List<T[]> splitArray(T[] items, int maxSubArraySize) {
  List<T[]> result = new ArrayList<T[]>();
  if (items ==null || items.length == 0) {
      return result;
  }

  int from = 0;
  int to = 0;
  int slicedItems = 0;
  while (slicedItems < items.length) {
      to = from + Math.min(maxSubArraySize, items.length - to);
      T[] slice = Arrays.copyOfRange(items, from, to);
      result.add(slice);
      slicedItems += slice.length;
      from = to;
  }
  return result;
}

#5


0  

You can use split with a special regular expression:

你可以使用分割和一个特殊的正则表达式:

 System.out.println(Arrays.toString(
     "Thisismystringiwanttosplitintogroupswith4chareach".split("(?<=\\G.{4})")
 ));

Credit to earlier post by Alan Moore. Please visit and vote up.

由艾伦·摩尔(Alan Moore)早些时候发表的文章。请访问并投票。

#6


0  

If actually you need quite big chunks, and don't want to modify their contents independently, consider reusing the same initial array by means of ByteBuffer.wrap() and then slice() repeatedly. This would prevent unnecessary copying and memory waste.

如果实际上您需要相当大的块,并且不想独立地修改它们的内容,可以考虑使用ByteBuffer.wrap()和slice()来重用相同的初始数组。这将防止不必要的复制和内存浪费。

#7


0  

Here is a function to split arrays, you can use below main method to test it.

这是一个分割数组的函数,您可以使用下面的main方法来测试它。

private static List<Integer[]> splitArray(Integer[] originalArray, int chunkSize) {
List<Integer[]> listOfArrays = new ArrayList<Integer[]>();
int totalSize = originalArray.length;
if(totalSize < chunkSize ){
   chunkSize = totalSize;
}
int from = 0;
int to = chunkSize;

while(from < totalSize){
    Integer[] partArray = Arrays.copyOfRange(originalArray, from, to);
    listOfArrays.add(partArray);

    from+= chunkSize;
    to = from + chunkSize;
    if(to>totalSize){
        to = totalSize;
    }
}
return listOfArrays;
}

Testing method:

测试方法:

public static void main(String[] args) {
List<Integer> testingOriginalList = new ArrayList<Integer>();

for(int i=0;i<200;i++){
    testingOriginalList.add(i);
}

int batchSize = 51;
Integer[] originalArray = testingOriginalList.toArray(new Integer[]{});

List<Integer[]> listOfArrays = splitArray(originalArray, batchSize);


for(Integer[] array : listOfArrays){
    System.out.print(array.length + ", ");
    System.out.println(Arrays.toString(array));
}
}

#8


0  

import java.util.Arrays;

public class Test {

    private void run() {
        try {

            byte[] cfsObjIds = "abcdefghij".getBytes();
            System.out.println(Arrays.toString(cfsObjIds));

            final int chunkSize = 4;
            System.out.println("Split by " + chunkSize + ":");
            int objQty = cfsObjIds.length;
            for (int i = 0; i < objQty; i += chunkSize) {
                int chunkUpperLimit = Math.min(objQty, i + chunkSize);
                byte[] cfsIdsChunk = Arrays.copyOfRange(cfsObjIds, i, chunkUpperLimit);

                System.out.println(Arrays.toString(cfsIdsChunk));
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        new Test().run();
    }
}