From: Mark Hubbart Date: 2004-05-10T13:19:00+09:00 Subject: Re: How to get the last 5 elements of an array? On May 8, 2004, at 11:01 PM, Gavin Sinclair wrote: > On Sunday, May 9, 2004, 9:04:07 AM, Jeff wrote: > > >> --- Gavin Sinclair wrote: >>> On Sunday, May 9, 2004, 7:23:12 AM, Jeff wrote: >>> >>> (where x == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) >>> >>>>> Yes the anomaly is that ruby only modularizes indices i for >>>>> -length <= i < length. A purist might say modular arithmetic >>>>> should be applied globally or not at all, but this would give >>>>> >>>>> x[10..15] == x[20..25] == x[-20..-15] == [1,2,3,4,5,6] >>> >>> I'd happily accept x[10..15] == x[20..25] == x[-20..-15] == [] >>> >>>>> which could fail to indicate Something's Wrong. I see ruby's >>>>> subset of modular arithmetic as a middle ground between convenience >>>>> and saftey. One can always write ModArray trivially, after all. >>> >>>> Whoa hang on, I didn't read the OP well enough. At least x[-3..2] >>>> should return [8, 9, 10, 1, 2, 3], otherwise this isn't even a >>>> subset of modular arithmetic, it's something else. >>> >>> Yes, it's Weird. >>> >> I am suddenly inclined to take a purist view of arrays: either modular >> arithmetic or no modular arithmetic. As such, there is only one rule >> to know: all the boundary cases are consistent and predictable. > > I'm not convinced by this. I like consistency as much as you do, but > there are different ways to achieve consistency. The main thing to > consider, perhaps, is complexity. You're shooting for an ultra-simple > approach, which is admirable, but I don't think either no-modular or > all-modular are that useful. > > And if you want > > (m..n).map { |i| arr[i] /* or arr[i % arr.size] */ } > > you know where to find it :) > > At the end of the day, I've never needed wraparound functionality > (arr[-4..6]), and I doubt I ever will. In fact, I doubt anyone will. I have. I wrapped my own replacement version of #[] and #[]= to get that functionality once. For me, it's the easiest (and, IMHO, clearest way to get the first and last elements in one swoop: max, min = values.sort[-1..0] I also used it when I did my learning exercise, coding the game of life in ruby. You need to go through each cell in a 2d array, and total the values of the immediately surrounding cells, wrapping over to the other end of the array if necessary. ..... .###. .#x#. .###. ..... ... where 'x' is the cell you are getting the total for, and '#' are teh cells you need the values of. the [-1..0] trick is especially handy for getting the middle row, straddling the center cell. There are other times I've used this, enough to where I have the function almost memorized from recoding it each time I need it. add me to the list of people who would like it built in, though :) Just never thought to mention it. >>> Take this, though. Let y = [7, 8]. Now what could y[-1..1] mean? >>> >>> (-1..1) =~ [-1, 0, 1]. All elements of that range represent >>> fair-game >>> indices into y. So: >>> >>> y[-1..1] == [8, 7, 8] ??? >>> > >> Since we have the ability to specify sets of integers inside [], I >> think we are forced to view y as a function. y[-1..1] == [8, 7, 8] is >> absolutely expected, to me. I put in 3 elements, I expect to get out >> 3 elements. This is consistent for all cases: put in n, get out n. >> We can make a truism of it, > >> y[a, b] == y[a..b] == [y[a], .. , y[b]] > > That's the mapping I coded above. > > A nitpick: y[a, b] is not intended to be the same as y[a..b]. > arr[n,5] means grab the 5 elements starting at index 'n'. > >> With the current ruby behavior, can you list all the conditions under >> which the above holds, and all the conditions and their outcomes when >> the above doesn't hold? Will you remember 8 months from now, or will >> you need to fire up irb to test it out again? > > Needing to fire up irb is one good test of how intuitive something is, > and there are a few Ruby features that cause me to use irb every time > I need them. However, I must accept that as part of life (and > different things are intuitive to different people), and you can turn > the negative into a positive: "Hey, I can just use irb to see what it > does". > >> As you can see, my bias is towards consistency. It's simply amazing >> how much code is devoted to special cases. That code is ugly and >> distracting. I'm not particularly purist, but I sure am when it comes >> to consistent behavior. I am borderline trolling now so I'll stop :) > > At the end of the day, I'd like a fairly complicated, but intuitive, > implementation for Array#[m..n]. It ain't gonna happen, though. The > current implementation is (I'm pretty sure) justified by some logic, > and the implementation I'd like to see treats Array more like an > ordered set than an array. > > a = [1, 3, 5, 7] > a[-1..1] # -> [7, 1, 3] > a[-10..10] # -> [1, 3, 5, 7] > a[-5..-1] # -> [1, 3, 5, 7] # The question that > # started this thread. > > b = [1, 2] > b[-1..1] # -> [2, 1] > # Not [2, 1, 2] > > Anyway, like I said, I don't see a great need for this stuff, although > I would like [-5..-1] to "work" in all cases. > > Cheers, > Gavin > > >