Java: équivalent de la plage de Python (int, int)?


99

Java a-t-il un équivalent à la range(int, int)méthode de Python ?


Voulez-vous dire une plage Python 2.x qui renvoie une liste, ou une plage Python 3.x qui renvoie un itérateur (équivalent à la plage x 2.x)? La première est relativement simple à implémenter comme d'autres l'ont fait ci-dessous, mais la version itérateur est un peu plus délicate.
Dave Kirby


Pour une gamme de tout Comparables, voir cette réponse
c0der

Pour une gamme avec pas à pas voir ceci
Sławomir Lenart

Réponses:


27

Guava fournit également quelque chose de similaire à celui de Python range:

Range.closed(1, 5).asSet(DiscreteDomains.integers());

Vous pouvez également implémenter un itérateur assez simple pour faire le même genre de chose en utilisant AbstractIterator de Guava:

return new AbstractIterator<Integer>() {
  int next = getStart();

  @Override protected Integer computeNext() {
    if (isBeyondEnd(next)) {
      return endOfData();
    }
    Integer result = next;
    next = next + getStep();
    return result;
  }
};

6
J'aurais aimé voir cela avant de mettre en place ma propre gamme générique. C'est bien mais c'est encore un autre rappel de la façon dont Java maladroit peut être comparé à des langages plus fonctionnels.
z7sg Ѫ

14
Range#asSetCela semble être devenu obsolète. Vous devez maintenant faire ceci:ContiguousSet.create(Range.closed(low, high), DiscreteDomain.integers())
Chthonic Project

quelle bibliothèque dois-je importer pour l'utiliser?
tgabb

À partir de Java 8, IntStream et LongStream ont des méthodes range et rangeClosed.
Jose Manuel Gomez Alvarez


16

Depuis Guava 15.0, Range.asSet () est obsolète et devrait être supprimé dans la version 16. Utilisez plutôt ce qui suit:

ContiguousSet.create(Range.closed(1, 5), DiscreteDomain.integers());

15

Je travaille sur une petite bibliothèque d'utils Java appelée Jools , et elle contient une classe Rangequi fournit les fonctionnalités dont vous avez besoin (il y a un JAR téléchargeable).
Les constructeurs sont soit Range(int stop), Range(int start, int stop)ou Range(int start, int stop, int step)(similaire à une boucle) et vous pouvez itérer à travers elle, qui a utilisé l' évaluation paresseuse, ou vous pouvez utiliser la toList()méthode pour obtenir explicitement la liste de gamme.

for (int i : new Range(10)) {...} // i = 0,1,2,3,4,5,6,7,8,9

for (int i : new Range(4,10)) {...} // i = 4,5,6,7,8,9

for (int i : new Range(0,10,2)) {...} // i = 0,2,4,6,8

Range range = new Range(0,10,2);
range.toList(); // [0,2,4,6,8]

14
public int[] range(int start, int stop)
{
   int[] result = new int[stop-start];

   for(int i=0;i<stop-start;i++)
      result[i] = start+i;

   return result;
}

Pardonnez toute erreur de syntaxe ou de style; Je programme normalement en C #.


étant donné que Vivien Barousse vous a battu à une réponse, pourquoi ne supprimez-vous pas la vôtre pour éviter toute duperie. À moins que vous ne prévoyiez vraiment de l'étoffer bien, bien sûr.
aaronasterling

9
Ils sont similaires; Je pense que le mien est un peu plus lisible. Son utilisation de la "longueur" est trompeuse, et je ne pense pas que la sienne réponde à la spécification Python (il inclut la borne supérieure, ce que network-theory.co.uk/docs/pytut/rangeFunction.html dit ne se produit pas en Python ). Si vous pensez que l'on est dupe, je pense que vous avez une réputation suffisante pour y faire face vous-même.
KeithS

10

Vous pouvez utiliser l'extrait de code suivant pour obtenir un ensemble de plages d'entiers:

    Set<Integer> iset = IntStream.rangeClosed(1, 5).boxed().collect
            (Collectors.toSet());

7
public int[] range(int start, int length) {
    int[] range = new int[length - start + 1];
    for (int i = start; i <= length; i++) {
        range[i - start] = i;
    }
    return range;
}

(Longue réponse juste pour dire "non")


Aussi, voyez que "range" en python 3 et le "xrange" préféré en Python 2 renvoient un objet "live" qui n'utilise pas de mémoire pour chaque élément qu'il contient. Ce serait encore plus gros à implémenter en Java.
jsbueno

3

Java 9 - IntStream::iterate

Depuis Java 9, vous pouvez utiliser IntStream::iterateet vous pouvez même personnaliser l'étape. Par exemple, si vous voulez un inttableau:

public static int[] getInRange(final int min, final int max, final int step) {
    return IntStream.iterate(min, i -> i < max, i -> i + step)
            .toArray();
}

ou List:

public static List<Integer> getInRange(final int min, final int max, final int step) {
    return IntStream.iterate(min, i -> i < max, i -> i + step)
            .boxed()
            .collect(Collectors.toList());
}

Et puis utilisez-le:

int[] range = getInRange(0, 10, 1);

2

La classe Range de Groovy peut être utilisée à partir de Java, bien qu'elle ne soit certainement pas aussi groovy.



1

Si vous avez l'intention de l'utiliser comme vous le feriez dans une boucle Python, Java boucle bien avec l'instruction for, ce qui rend cette structure inutile à cette fin.


5
Vous ne l'utilisez généralement pas non plus pour une boucle en python. Il y a presque toujours une manière plus propre d'itérer.
Daenyth

Eh bien, la plage est généralement utilisée dans une boucle for. Mais les boucles for sont souvent utilisées sans portée.
FogleBird

1
IntStream.range(0, 10).boxed().collect(Collectors.toUnmodifiableList());

1
Cela vous aiderait si vous expliquiez comment ce code résout le problème.
Robert Columbia

0

Je sais que c'est un ancien article, mais si vous recherchez une solution qui renvoie un flux d'objets et que vous ne voulez ou ne pouvez pas utiliser de dépendances supplémentaires:

Stream.iterate(start, n -> n + 1).limit(stop);

start - stop inclus - exclusif

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.