web-dev-qa-db-fra.com

Fractionner le tableau en morceaux de longueur X

Actuellement, j'ai un tableau de taille N. J'essaie de copier chaque X octets du tableau.

Exemple si le tableau est de taille 10 et que je veux des tableaux de taille 3. Je copierais les 3 premiers éléments, puis les 3 suivants et le dernier.

Actuellement, j'utilise l'algorithme suivant:

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.

Existe-t-il un moyen plus efficace ou plus décent de faire ce que je veux? Cet algorithme semble très mauvais = l

Des idées comment je peux l'améliorer ou au moins un indice?

12
Brandon

Et ça:

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);
10
arshajii

Voici une méthode pratique qui convertit un byte[] en un tableau de byte[]. Donc, le résultat est un byte[][].

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;
}

Quelques avantages par rapport à la précédente meilleure réponse :

  1. La condition for utilise un <= qui a plus de sens que < ... + 1.
  2. Le fait de placer l'index d'arrêt dans un champ temporaire réduit le nombre de calculs dans le dernier bloc if.

(Testé à l'unité)

7
bvdb

Peu de choses à faire ici:

Premièrement, les conventions courantes fronçant les sourcils après avoir utilisé des majuscules pour commencer les noms de variable, modifiez les variables I et NewArray en 'i' et 'newArray' respectivement.

Ensuite, votre code ne fonctionne pas car votre première fois dans la boucle, i-3 mènera à une exception IndexOutOfBounds .....

Enfin, vous n'indiquez pas comment vous définissez la taille du tableau 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 --;
}
3
rolfl

Voici mon implémentation pour cela, il divisera votre tableau en sous-tableaux d'une taille maximale que vous déciderez, et placera les sous-tableaux dans une liste de tableaux. Le dernier tableau sera plus petit si sa taille n'est pas un multiple de la taille maximale choisie.

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;
}
2
Gubatron

Vous pouvez utiliser split avec une expression régulière spéciale:

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

Crédit à message précédent par Alan Moore. S'il vous plaît visitez et votez.

0
henderso
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();
    }
}
0
Splash

Je sais que cette question est assez ancienne, mais bon, quelqu'un pourrait chercher une autre réponse propre à Java pour cette question courante. Si vous travaillez avec List (Java 7), il existe une méthode assez simple et propre pour obtenir une partie d'une liste: List.subList (fromIndex, toIndex)

C'est simple à utiliser. Si je prends l'exemple de la question, ce serait comme:

int chunkSize = 3;
int counter = 0;
// bytes must be a List like an ArrayList
List<Byte> byteList = Arrays.asList(bytes);
int length = byteList.size(); 
for (int fromIndex = 0; fromIndex < length; fromIndex += chunkSize) {
   int toIndex = fromIndex + chunkSize;
   if(toIndex > length){
      toIndex = length;
   }
   NewArray[counter] = byteList.subList(fromIndex, toIndex);
   counter++;
}
// Now NewArray[] contain sub array and the last one is of the remaining length

Pour contourner le 'compteur', certains pourraient changer la façon dont NewArray est construit pour une approche List , avec quelque chose comme:

// NewArray must be a List<List<Byte>>
NewArray.addAll(byteList.subList(fromIndex, toIndex));

J'espère que cela aidera quelqu'un dans le futur!

0
CtrlX

Voici une fonction pour diviser des tableaux, vous pouvez utiliser la méthode principale ci-dessous pour le tester.

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;
}

Méthode d'essai:

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));
}
}
0
Evan Hu

Si vous avez réellement besoin de gros morceaux et que vous ne souhaitez pas modifier leur contenu indépendamment, envisagez de réutiliser le même tableau initial au moyen de ByteBuffer.wrap(), puis de slice() à plusieurs reprises. Cela éviterait les copies inutiles et le gaspillage de mémoire.

0
leventov