From: Meino Christian Cramer Date: 2004-08-17T17:51:11+09:00 Subject: Re: Q: Shifting a hash anf and array From: "Robert Klemme" Subject: Re: Q: Shifting a hash anf and array Date: Tue, 17 Aug 2004 17:21:01 +0900 Hi Martin, Hi Robert, thank you very much for your sources ! Great! :) I have an additional question below.....vvvvvv > > "Martin DeMello" schrieb im Newsbeitrag > news:u_gUc.122944$M95.4319@pd7tw1no... > > Meino Christian Cramer wrote: > > > > > > Contents of the array before the trick: > > > > > > 1 2 3 4 5 6 7 8 9 0 index > > > A B C D E F G H I J contents > > > > > > (execute *trick*) > > > > > > Contents of the array after the trick: > > > > > > 1 2 3 4 5 6 7 8 9 0 index > > > J A B C D E F G H I contents > > > > array.unshift(array.pop) > > or array.push(array.shift) for the other direction. > > > > And now the shift of an hash: > > > > > > Contents of the hash before the trick: > > > > > > A B C D E F G H I J key > > > 1 2 3 4 5 6 7 8 9 0 value > > > > > > (execute *trick*) > > > > > > Contents of the hash after the trick: > > > > > > A B C D E F G H I J key > > > 0 1 2 3 4 5 6 7 8 9 value > > > > > > Both are very similiar. > > > > Not really :) Hashes are inherently unordered, so the concept of a > > rotation is a bit trickier. This works on the assumption that > > Hash#values returns values in positions corresponding to the keys in > > Hash#keys... > > > > class Array > > def rot1 > > unshift(pop) > > end > > end > > > > Hash[*(hash.keys.rot1.zip(hash.values.rot1).flatten)] > > Hm, IMHO there is one "rot1" too much: you're rotating keys *and* values > while you should only rotate one of them. Otherwise I figure the result > will be the same as the original hash... :-) > > The other drawback of your solution is that it relys on #keys and #values > returning elements in matching order, i.e., if you zip both you get the same > hash. Although that might work it makes me feel a bit wary because AFAIK > it's not a guaranteed property of Hash (and I wouldn't want to rely on it). > This might even change over time if the Hash implementation was changed for > any reasons. > > How about these one liners, that avoids the problem: > > h = {0=>"a", 1=>"b", 2=>"c"} > # put rotated in h2 > (h2={}).send(:[]=, *h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2, v1]}) I tried to understand this... "h = {0=>"a", 1=>"b", 2=>"c"}" generates an hash...ok "(h2={}).send(:[]=" generates h2, another hash and sends to its []= (element assignment) the.... "*h.sort.inject {|(k1,v1),(k2,v2)| h2[k1]=v2; [k2, v1]})" ...?... I stumbled over the "*" at *h.sort.....What does it mean? > # rotate inplace > h.send(:[]=, *h.sort.inject {|(k1,v1),(k2,v2)| h[k1]=v2; [k2, v1]}) ...same here... > :-) > > Note: you can omit the sort in the first example, but IMHO an order should > be imposed on keys. Otherwise the rotation does not make much sense IMHO. Absolutely correct. I was searching for something like "an array with indices not being integers but ordered". > You can omit the sort in the second example, too, which seems to work > because the set of keys of the hash doesn't change. But this seems a bit > hackish to me, too. You can substitute "sort" by "dup" though. > > Kind regards > > robert > > > PS: Enumerable#inject is cool. ;-) PS: Undertstanding and writing such code is much cooler... ! Ruby.use! Meino