From: Robert Klemme on
2010/6/4 Marcin Wolski <wolskint(a)o2.pl>:
> Robert Dober wrote:
>> On Fri, Jun 4, 2010 at 3:41 AM, Marcin Wolski <wolskint(a)o2.pl> wrote:
>> <snip>
>>> �def ==(other)
>>> �@email == other.email
>>> �end
>> this seems ok
>>>
>>> �alias eql? ==
>>>
>>> �def hash
>>> � �code = 17
>>> � �code = 37*code + @email.hash
>>> end
>>>
>> Are you sure you want to do this? "equal" objects would overwrite each
>> other when used as hash keys. This is normally not a good idea, be
>> sure you really want/need this!

Absolutely agree!

> What would be the other possible solution to this problem?

Actually I am not sure what the problem actually is. Does OP want to
return all objects which are in both Arrays? Does he want to return
all objects which share a particular set of properties? etc. Before
we can provide solutions we have to know what problem must be solved.

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

From: Anderson Leite on
Before
> we can provide solutions we have to know what problem must be solved.
>
> Kind regards
>
> robert



I have a list of objects that came from database and another list of
objects extracted from a xml. I need the elements who are in both lists.


Then...I thought to compare objects overriding the == method like Marcin
Wolski wrote. There is another solution ?
--
Posted via http://www.ruby-forum.com/.

From: Robert Klemme on
On 05.06.2010 00:35, Anderson Leite wrote:
> Before
>> we can provide solutions we have to know what problem must be solved.

> I have a list of objects that came from database and another list of
> objects extracted from a xml. I need the elements who are in both lists.
>
>
> Then...I thought to compare objects overriding the == method like Marcin
> Wolski wrote. There is another solution ?

If all objects you are dealing with implement #eql? and #hash in a way
to be suitable for that comparison then using #eql? is the most
straightforward approach.

If they do not and you want to do the comparison based on other criteria
then you need to pick a different solution. For example:

in_both = obj_from_db.select do |u1|
obj_from_xml.any? do |u2|
u1.email == u2.email && u1.age == u2.age
end
end

The larger set should be used for the outer iteration. If both sets are
really large then you probably rather want to use a different strategy
by speeding up access via a Hash. For that you need a specific Hash key
(remember, we had assumed #eql? and #hash cannot be used). That key
must implement #eql? and #hash; the easiest way to get such a Key class
is to use Struct:

Key = Struct.new :email, :age

db_index = {}

obj_from_db.each do |u1|
db_index[Key[u1.email, u1.age]] = u1
end

in_both = obj_from_xml.select do |u2|
db_index[Key[u2.email, u2.age]]
end

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
From: Robert Dober on
On Sat, Jun 5, 2010 at 2:35 PM, Robert Klemme
<shortcutter(a)googlemail.com> wrote:
> On 05.06.2010 00:35, Anderson Leite wrote:
>>
>>  Before
>>>
>>> we can provide solutions we have to know what problem must be solved.
>
>> I have a list of objects that came from database and another list of
>> objects extracted from a xml. I need the elements who are in both lists.
>>
>>
>> Then...I thought to compare objects overriding the == method like Marcin
>> Wolski wrote. There is another solution ?
>
> If all objects you are dealing with implement #eql? and #hash in a way to be
> suitable for that comparison then using #eql? is the most straightforward
> approach.
Not #eql?, #== please.
Cheers
R.
--
The best way to predict the future is to invent it.
-- Alan Kay

From: Rein Henrichs on
First, let's be clear about the semantics of the various comparison methods:

The == operator checks whether two objects are equal (after coercing
them to the same type).

1 == 2 # => false
1 == 1.0 # => true

#eql? checks if two objects are equal and of the same type.

1.eql? 1.0 # => false
'a'.eql? 'a' # => true

#equal? checks if two objects are identical (the same object).

'a'.equal? 'a' # => false
:a.equal? :a # => true

As a mnemonic, note that their strictness is a function of their length.

Now, on to the original question, which (paraphrased) is:

"How can I get arrays of custom objects to work as expected with the
set intersection operator &?"

The Array#& operator, like its siblings, uses the #hash and #eql?
methods of the objects it compares. These must be the same for objects
you want to be considered equivalent.

Armed with this knowledge, let's define those methods on User. For instance:

class User

# checks if objects are equal
def ==(other)
@email == other.email
end

# checks if objects are equal and the same class
def eql?(other)
self == other && self.class == other.class
end

# unique hash based on email and class
# We add 1 to prevent User.new('').hash == User.hash
# NOTE: Users with @email == nil will have the same hash and modify
if necessary.
def hash
@email.hash ^ self.class.hash +
end
end

This will allow:

> [User.new('bob(a)example.com')] & [User.new('bob(a)example.com')]
=> [#<User:0x1016dcdb8 @email="bob(a)example.com">]

Which I believe was the original intent. Keep in mind that this will
also cause Hash to see them as the same object for keys, which is
probably also expected

As an aside, I would also like to comment that the following, from one
of the responses:

def to_s
"#@email"
end

is unnecessarily complex and can be replaced simply with:

def to_s
@email
end

Don't use string interpolation when you don't need it. If you want to
ensure that @email is a string, call to_s on it instead.

On 2010-06-03 15:29:55 -0700, Anderson Leite said:
>
> I need to compare two arrays of users, and get and third array just with
> the matches. I found the "&" method that work for Fixnuns and String,
> but...how to use with objects ?
>
>
> class User
> attr_accessor :email
> end
>
> a = User.new
> a.email = 'ruby(a)rails.com'
>
> b = User.new
> b.email = 'ruby(a)rails.com'
>
> array_one = [a]
> array_two = [b]
>
>
> array_three = array_one & array_two
>
> puts array_three # I want the user here
>
>
>
> Can you help me ?
> thanks

Rein Henrichs
http://puppetlabs.com
http://reinh.com

First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9
Prev: [ANN] Money 3.0.2
Next: escape character with decimal value