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