Reputation: 357
I have been breaking my head over this
I want to create a list of intervals (as Tuple2 instances) of a range between min
and max
divided in numberOfIntervals
.
This particular project is in java (no scala allowed), so i am using vavr, but any scala solution i could probably translate to vavr
This is my solution:
final int numberOfIntervals = 7;
final int min = 1;
final int max = 100;
final int targetSize = (max - min) / numberOfIntervals + 1;
final List<Tuple2<Integer, Integer>> l = Iterator.rangeClosed(min, max)
.grouped(targetSize)
.map(l -> Tuple.of(l.head(), l.last())).toList();
This works:
(1, 15)
(16, 30)
(31, 45)
(46, 60)
(61, 75)
(76, 90)
(91, 100)
But this is created long intermediary lists. I have also been playing with something like this:
final int numberOfIntervals = 7;
final int min = 1;
final int max = 100;
final int targetSize = (max - min) / numberOfIntervals + 1;
final List<Tuple2<Integer, Integer>> l = Iterator
.rangeClosedBy(min, max + targetSize, targetSize).sliding(2)
.map(s -> of(s.get(0), s.get(1) - 1))
.toList();
But with this the last range is larger than the max value:
(1, 15)
(16, 30)
(31, 45)
(46, 60)
(61, 75)
(76, 90)
(91, 105)
Upvotes: 2
Views: 1313
Reputation: 357
Based on the suggestions of Piotr Wilkin i came up with the following
final int numberOfIntervals = 7;
final int min = 1;
final int max = 100;
final int targetSize = (int) Math.ceil((max - min) / numberOfIntervals) ;
final List<Tuple2<Integer, Integer>> l = Iterator
.rangeBy(min, max + targetSize, targetSize).sliding(2)
.map(s -> of(s.get(0), s.get(1)-1))
.map(t->t.map2(i->Math.min(i,max)))
.toList();
Upvotes: 0
Reputation: 3501
Your second code is better, but you won't get far with any code that's trying to compute regular intervals simply because the last interval is an exception - however you do it, you'll have to somehow include a condition that cuts its size.
I'd suggest using rangeBy
instead of rangeClosed
, that should get you a proper collection of the starting elements. You already have the interval size, although instead of hardcoding +1
(which will yield an incorrect result if your number of intervals divides the range size without a remainder) you might want to use Math.ceil()
. Afterwards, you just want to map the starting numbers with map(x -> Tuple.of(x, Math.min(x + targetSize - 1, max)))
.
Upvotes: 1