Java: odpowiednik zakresu Pythona (int, int)?

99

Czy Java ma odpowiednik range(int, int)metody Pythona ?

Nick Heiner
źródło
Czy masz na myśli zakres Pythona 2.x, który zwraca listę, czy zakres Pythona 3.x, który zwraca iterator (odpowiednik 2.x xrange)? Pierwsza z nich jest stosunkowo prosta do zaimplementowania, tak jak inne zrobiły to poniżej, ale wersja iteratora jest nieco bardziej skomplikowana.
Dave Kirby
Szereg dowolnych odpowiedzi można Comparableznaleźć w tej odpowiedzi
dok
Zakres ze steppingiem można znaleźć w tym
Sławomir Lenart

Odpowiedzi:

27

Guava zapewnia również coś podobnego do Pythona range:

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

Możesz również zaimplementować dość prosty iterator, aby zrobić to samo, używając AbstractIterator Guavy:

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

  @Override protected Integer computeNext() {
    if (isBeyondEnd(next)) {
      return endOfData();
    }
    Integer result = next;
    next = next + getStep();
    return result;
  }
};
Simon Steele
źródło
6
Żałuję, że nie widziałem tego, zanim wdrożyłem mój własny ogólny zakres. To fajne, ale to kolejne przypomnienie, jak niezgrabną Javę można porównać do bardziej funkcjonalnych języków.
z7sg Ѫ
14
Range#asSetwydaje się, że jest przestarzały. Teraz musisz to zrobić:ContiguousSet.create(Range.closed(low, high), DiscreteDomain.integers())
Projekt Chthonic
jaką bibliotekę muszę zaimportować, aby z tego skorzystać?
tgabb
Od Java 8, IntStream i LongStream mają metody range i rangeClosed.
Jose Manuel Gomez Alvarez,
225

Stare pytanie, nowa odpowiedź (dla Java 8)

    IntStream.range(0, 10).forEach(
        n -> {
            System.out.println(n);
        }
    );

lub z odniesieniami do metod:

IntStream.range(0, 10).forEach(System.out::println);
jhodges
źródło
1
Jaki pakiet? jak to zaimportować?
Justin Thomas,
6
@Justin To jest funkcja języka java 8.
Tzafrir
16

Od wersji Guava 15.0 funkcja Range.asSet () jest przestarzała i jest planowana do usunięcia w wersji 16. Zamiast tego użyj następującego:

ContiguousSet.create(Range.closed(1, 5), DiscreteDomain.integers());
jiehanzheng
źródło
15

Pracuję nad małą biblioteką narzędzi Java o nazwie Jools , która zawiera klasę, Rangektóra zapewnia potrzebną funkcjonalność (jest JAR do pobrania).
Konstruktorami są albo Range(int stop), Range(int start, int stop)albo Range(int start, int stop, int step)(podobnie jak pętla for) i możesz albo iterować po niej, która używa leniwej oceny, albo możesz użyć jej toList()metody, aby jawnie uzyskać listę zakresów.

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]
Amir Rachum
źródło
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;
}

Wybacz wszelkie błędy składniowe lub stylowe; Zwykle programuję w C #.

KeithS
źródło
biorąc pod uwagę, że Vivien Barousse pokonała cię w odpowiedzi, dlaczego nie usuniesz swojej, aby uniknąć jakiegokolwiek oszustwa. Chyba że naprawdę planujesz ładnie go ukształtować.
aaronasterling
9
Są podobne; Myślę, że moje jest trochę bardziej czytelne. Użycie przez niego „length” jest mylące i nie sądzę, aby spełniał on specyfikację Pythona (zawiera górną granicę, o której network-theory.co.uk/docs/pytut/rangeFunction.html mówi, że nie występuje w Pythonie ). Jeśli uważasz, że jesteś naiwniakiem, sądzę, że masz wystarczającą reputację, aby sobie z tym poradzić.
KeithS
10

Możesz użyć następującego fragmentu kodu, aby uzyskać zestaw liczb całkowitych z zakresu:

    Set<Integer> iset = IntStream.rangeClosed(1, 5).boxed().collect
            (Collectors.toSet());
juliański
źródło
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;
}

(Długa odpowiedź, wystarczy powiedzieć „Nie”)

Vivien Barousse
źródło
Zobacz również, że „zakres” w Pythonie 3 i preferowany „xrange” w Pythonie 2 zwracają „aktywny” obiekt, który nie zużywa pamięci dla każdego elementu, który zawiera. To byłoby jeszcze większe do zaimplementowania w Javie.
jsbueno
3

Java 9 - IntStream::iterate

Od wersji Java 9 możesz używać, IntStream::iteratea nawet dostosowywać krok. Na przykład, jeśli chcesz mieć inttablicę:

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

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

A następnie użyj go:

int[] range = getInRange(0, 10, 1);
michalk
źródło
2

Sprytną klasę Range Groovy można używać w Javie, choć z pewnością nie jest tak fajna.

Jan
źródło
1

Jeśli zamierzasz używać go tak, jak w pętli Pythona, Java ładnie zapętla się z instrukcją for, co sprawia, że ​​ta struktura jest niepotrzebna do tego celu.

Nikki9696
źródło
5
Zwykle nie używasz go również do pętli w Pythonie. Prawie zawsze istnieje czystszy sposób na iterację.
Daenyth,
Cóż, zakres jest zwykle używany w pętli for. Ale pętle są często używane bez zasięgu.
FogleBird
1
IntStream.range(0, 10).boxed().collect(Collectors.toUnmodifiableList());
Pierre
źródło
1
Pomogłoby, gdybyś wyjaśnił, jak ten kod rozwiązuje problem.
Robert Columbia
0

Wiem, że to stary post, ale jeśli szukasz rozwiązania, które zwraca strumień obiektów i nie chcesz lub nie możesz użyć żadnych dodatkowych zależności:

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

start - włącznie stop - ekskluzywny

HDubz
źródło