There must be a more elegant way to do this

Hello,

I have a bunch of arrays containing records retrieved from the
database in separate queries. That can't be changed - I have deal with
the different arrays of these records. Each of these records contains,
amongst other data fields, two ids - a user_id and an address_id.

Now my task is to take all these records in different arrays and
extract out an array of unique records from them (unique combination
of user_id and address_id) as the same record may be present in
multiple arrays.

One way to do it is to brute force it by extracting, looping and
finding each user_id and address_id combination - but that is not
clean. Given the elegance Ruby affords, I believe there must a better
way to do this. Appreciate any thoughts on how to go about doing this.

Thanks,
-S

(array1 + array2 + array3).uniq

or

[array1, array2, array3].flatten.uniq

I think the problem with doing that is that the arrays contain instances of models.

Sounds like skt wants to consider an instance unique based on only two attributes of each instance.

The best way might just to loop over the arrays and append them to a 4th array if the 4th array doesn’t already contain the item. Might be able to turn it into a one-liner using inject or map, but that might not be readable.

Thanks Michael and Tim.

I think the problem with doing that is that the arrays contain instances of
models.

Sounds like skt wants to consider an instance unique based on only two
attributes of each instance.

That's correct Tim - I am looking to uniq them only on the two id
fields

The best way might just to loop over the arrays and append them to a 4th
array if the 4th array doesn't already contain the item. Might be able to
turn it into a one-liner using inject or map, but that might not be
readable.

I will give this a try. Welcome any additional thoughts or
suggestions.

-S

Try pass the block:

(array1 + array2 + arrayN].uniq { |instance| [instance.user_id, instance.address_id]}

undocumented feature

nice.

Or if you only want those two fields:

(array1 + array2 + arrayN).map{|instance| [instance.user_id,
instance.address_id]}.uniq

(unless that's *exactly* the same thing :wink:

I think the problem with doing that is that the arrays contain instances of
models.

I .uniq arrays of instances of models all the time - it's a very handy tool.

u1 = User.first

=> #<User id: 1, name: "mgp", person_id: 6, created_at: "2010-01-23
18:49:58", updated_at: "2010-05-09 20:02:47", role_name:
"super_admin">

u1.object_id

=> -614919958

u2 = User.first

=> #<User id: 1, name: "mgp", person_id: 6, created_at: "2010-01-23
18:49:58", updated_at: "2010-05-09 20:02:47", role_name:
"super_admin">

u2.object_id

=> -614928398

[u1, u2].uniq

=> [#<User id: 1, name: "mgp", person_id: 6, created_at: "2010-01-23
18:49:58", updated_at: "2010-05-09 20:02:47", role_name:
"super_admin">]

Sounds like skt wants to consider an instance unique based on only two
attributes of each instance.

If so, then collecting up just those values and .uniq on them would
still be readable, as a one liner or broken into a couple, or doing a
.group_by and checking the size of the hash....

(some sample data from the OP would help clarify things if it's still
an issue after the suggestions)

M

I think the problem with doing that is that the arrays contain instances of
models.
I .uniq arrays of instances of models all the time - it’s a very handy tool.

Agreed, but it doesn’t solve the problem when you only want unique instances based on some of the fields.

Sounds like skt wants to consider an instance unique based on only two
attributes of each instance.

If so, then collecting up just those values and .uniq on them would
still be readable, as a one liner or broken into a couple, or doing a
.group_by and checking the size of the hash…

Agreed once again, but that only gets you the unique address_ids and user_ids, not the full instances. Not sure if that would matter for his requirements

Cheers!

Thank you all for your suggestions.

My apologies, I should have mentioned this before but I thought once I
figure out how to get uniq records based on combination of user_id and
address_id I could figure out the rest. Essentially amongst other
fields, each of these records contains a computed distance field i.e.
how far is that user/address from a point. That distance could be
different so while user_id and address_id could be same other fields
may not be same.

What I need to do is get unique user_id/address_id records with the
shortest distance.

Thanks again!
-S

Why? I suspect you could do what you want much more easily using
ActiveRecord to get the data for you directly. Assuming you have
ActiveRecord models of course.

Colin

Well, that's other one task and not just .uniq. Magic unuseful :slight_smile:

You'd better to write much more complex clause:

(array1 + array2 + arrayN).group_by { |instance| [instance.user_id, address_id] }.values.collect { |array| array.sort {|a,b| a.distance <=> b.distance}.first}

Now that looks like Ruby elegance - everything in one line of code!

Thanks Valery!

Hello,

I have a bunch of arrays containing records retrieved from the

database in separate queries. That can’t be changed - I have deal with

the different arrays of these records. Each of these records contains,

amongst other data fields, two ids - a user_id and an address_id.

Does each array hold the same or different type of object?

-Conrad

When you say you have arrays are these actual arrays or are they the
result of ActiveRecord find queries, which are like arrays but are not
actually arrays?

Colin

> Hello,

> I have a bunch of arrays containing records retrieved from the
> database in separate queries. That can't be changed - I have deal with
> the different arrays of these records. Each of these records contains,
> amongst other data fields, two ids - a user_id and an address_id.

When you say you have arrays are these actual arrays or are they the
result of ActiveRecord find queries, which are like arrays but are not
actually arrays?

These are result of ActiveRecord queries. I thought they were arrays
of database record objects - could you please help me understand how
they are different from normal arrays?

The result of Model.where( some_condition ), for example, is an
ActiveRecord::Relation object rather than an array. You can for
example apply further .where operations on it to refine the search
further.

Colin