> You could wrap your keys in a custom class. For added convenience you
> could also wrap Hash with another class which wraps keys on insertion
> and unwraps on reading.
> ...
>
> In that case I'd probably rather do this:
>
> my_array.inject({}) {|hs, obj| hs[obj.key] ||= obj; hs }.values
Now I remember why I wanted my earlier approach. My object has
several Array member variables. By default, my #hash and #eql?
methods use all of them. In one case I need to ignore 2 of the 4
arrays, e.g. for a uniqueness hash. I can use your second method
thus.
my_array.inject({}) {|hs, obj| hs[obj.arr1 + obj.arr2] ||= obj;
hs }.values
Appending is not safe:
[1,2] + [3,4,5] -> [1,2,3,4,5]
[1,2,3] + [4,5] -> [1,2,3,4,5]
You want to be creating new arrays with two elements:
my_array.inject({}) {|hs, obj| hs[[obj.arr1, obj.arr2]] ||= obj; hs }.values
But won't this create a bevy of new Array objects with the "+" method
(two for each item in the original array)?
Yes, but I'd rather first try the suggestion above out before starting
to think about optimizations.
I could instead pre-hash
the values something like the following.
my_array.inject({}) {|hs, obj| hs[obj.arr1.hash ^ obj.arr2.hash] ||=
obj; hs }.values
That's a bad idea because of the nature of hash values, as you
correctly identified:
This avoids the new Array spew, but I will lose unique objects if my
fabricated hash keys clash (i.e. same hash key for unique arrays). If
I can specify different methods to use in place of #hash and #eql?, I
can get the same behavior without the performance penalty. (My code
is already slow.)
I think I'll use your wrapping Hash idea. Thanks!
I'd start with the other approach which is considerably easier.
robert
···
2007/5/24, Ryan Hinton <iobass@email.com>:
On May 23, 12:18 pm, Robert Klemme <shortcut...@googlemail.com> wrote:
--
Have a look: Robert K. | Flickr