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

On 3 June 2011 17:49, skt [email protected] wrote:

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.

(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.

On Jun 3, 11:19am, Tim S. [email protected] wrote:

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

On 3 June 2011 19:19, Tim S. [email protected] wrote:

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

On Friday, June 3, 2011 3:09:55 PM UTC-4, pavling wrote:

On 3 June 2011 19:19, Tim S. [email protected] wrote:

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

On 3 June 2011 19:30, Valery K. [email protected] wrote:

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:

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}

On 3 June 2011 17:49, skt [email protected] wrote:

Hello,

I have a bunch of arrays containing records retrieved from the
database in separate queries. That can’t be changed

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

On Fri, Jun 3, 2011 at 9:49 AM, skt [email protected] wrote:

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

On 3 June 2011 17:49, skt [email protected] wrote:

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?

Colin

On Jun 3, 1:39pm, Valery K. [email protected] wrote:

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!

On 5 June 2011 07:45, skt [email protected] wrote:

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

On Jun 4, 12:57am, Colin L. [email protected] wrote:

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?