Java: Equivalente ao intervalo do Python (int, int)?


99

Java tem um equivalente ao range(int, int)método do Python ?


Você quer dizer um intervalo Python 2.x que retorna uma lista ou um intervalo Python 3.x que retorna um iterador (equivalente a 2.x xrange)? O primeiro é relativamente simples de implementar, como outros fizeram abaixo, mas a versão do iterador é um pouco mais complicada.
Dave Kirby


Para uma faixa de qualquer Comparables, veja esta resposta
c0der

Para um intervalo com stepping veja isto
Sławomir Lenart

Respostas:


27

O Guava também fornece algo semelhante ao do Python range:

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

Você também pode implementar um iterador bastante simples para fazer o mesmo tipo de coisa usando AbstractIterator do 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
Eu gostaria de ter visto isso antes de implementar minha própria linha genérica. É bom, mas ainda outro lembrete de como o Java desajeitado pode ser comparado a linguagens mais funcionais.
z7sg Ѫ

14
Range#asSetparece ter se tornado obsoleto. Agora você precisa fazer isso:ContiguousSet.create(Range.closed(low, high), DiscreteDomain.integers())
Projeto Chthonic

que biblioteca preciso importar para usar isso?
tgabb

No Java 8, IntStream e LongStream têm os métodos range e rangeClosed.
Jose Manuel Gomez Alvarez


16

Desde o Guava 15.0, Range.asSet () se tornou obsoleto e está programado para ser removido na versão 16. Use o seguinte:

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

15

Estou trabalhando em uma pequena biblioteca de utilitários Java chamada Jools , e ela contém uma classe Rangeque fornece a funcionalidade de que você precisa (há um JAR para download).
Construtores são ou Range(int stop), Range(int start, int stop)ou Range(int start, int stop, int step)(semelhante a um loop) e você pode iterate através dele, que costumava avaliação preguiçosa, ou você pode usar o seu toList()método para obter explicitamente a lista de gama.

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

Perdoe quaisquer erros de sintaxe ou estilo; Eu normalmente programo em C #.


dado que Vivien Barousse chegou antes de você, por que não deleta a sua para evitar qualquer engano. A menos que você realmente planeje aprimorá-lo, é claro.
aaronasterling

9
Eles são semelhantes; Acho que o meu é um pouco mais legível. Seu uso de "comprimento" é enganoso e não acho que ele atenda às especificações do Python (ele inclui o limite superior, que network-theory.co.uk/docs/pytut/rangeFunction.html diz que não acontece no Python ) Se você acha que alguém é um ingênuo, acredito que tem reputação suficiente para lidar com isso sozinho.
KeithS

10

Você pode usar o seguinte snippet de código para obter um conjunto de intervalo de inteiros:

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

(Resposta longa apenas para dizer "Não")


Além disso, veja que "range" em Python 3 e o "xrange" preferido em Python 2 retornam um objeto "live" que não usa memória para cada item que contém. Isso seria ainda maior para implementar em Java.
jsbueno

3

Java 9 - IntStream::iterate

Desde o Java 9 você pode usar IntStream::iteratee até personalizar a etapa. Por exemplo, se você deseja intarray:

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

E então use-o:

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

2

A elegante classe Range do Groovy pode ser usada em Java, embora certamente não seja tão legal.



1

Se você pretende usá-lo como faria em um loop Python, o Java executa um loop bem com a instrução for, o que torna essa estrutura desnecessária para esse propósito.


5
Você normalmente não o usa para um loop em python. Quase sempre há uma maneira mais limpa de iterar.
Daenyth

Bem, range geralmente é usado em um loop for. Mas os loops for são freqüentemente usados ​​sem intervalo.
FogleBird

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

1
Ajudaria se você explicasse como esse código resolve o problema.
Robert Columbia

0

Eu sei que esta é uma postagem antiga, mas se você está procurando uma solução que retorna um fluxo de objeto e não deseja ou não pode usar nenhuma dependência adicional:

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

início - parada inclusiva - exclusivo

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.