From: "Jesús Gabriel y Galán" Date: 2013-06-18T05:40:23+09:00 Subject: Re: Compare and sort one array according to another. On Mon, Jun 17, 2013 at 10:39 PM, Jesús Gabriel y Galán wrote: > On Mon, Jun 17, 2013 at 9:56 PM, masta Blasta wrote: >> Joel Pearson wrote in post #1112686: >>> masta Blasta wrote in post #1112677: >>>> Joel Pearson wrote in post #1112665: >>>>> If the items within each array belong to each other, how about a >>>>> multidimensional array? >>>>> >>>>> arr = [ >>>>> [ Obj1(prop1, prop2, id), OthrObj1(prop1, prop2, ref_id) ], >>>>> [ Obj2(prop1, prop2, id), OthrObj2(prop1, prop2, ref_id) ], >>>>> [ Obj3(prop1, prop2, id), OthrObj3(prop1, prop2, ref_id) ] >>>>> ] >>>>> >>>>> >>>>> All the sorting is dealt with together then: >>>>> >>>>> sorted_arr = arr.sort_by { |obj1, obj2| obj1.id } >>>> >>>> I don't quite understand everything that's happening here. Can you >>>> elaborate a bit more on your solution. >>> >>> I'm going by your comment here: >>> "The objects in arr2 have a 1-1 relationship with the objects in arr1" >>> >>> If the objects are interlinked, rather than trying to keep two separate >>> arrays and sorting them side-by-side (which can easily go wrong), you >>> could simply connect the pairs into their own arrays all inside another >>> array. >>> >>> This has the benefit that once you put the pair into their own array, >>> they are connected without you having to worry about having to do >>> everything the same with array1 and array2. >>> >>> Then you can iterate through the large array like this: >>> >>> arr.each { |subarray| some_method( subarray[0], subarray[1] ) } >>> >>> In this example you can access each of the smaller arrays inside your >>> array. [0] is each object and [1] is each otherobject >>> >>> Or like this: >>> >>> arr.each { |object, otherobject| some_method( object, otherobject ) } >>> >>> This example is functionally the same as the previous one, but you're >>> using parallel assignment to place each object from the array into its >>> own variable so it's easier to read. >>> >>> Using this approach, you can sort the larger array containing objects >>> and otherobjects by whatever criteria you want, and they'll stay >>> together as a pair within the larger array. >>> >>> This will sort each array within the parent by the first object's id: >>> >>> arr = arr.sort_by { |object, otherobject| object.id } >>> >>> This does the same thing, but with the second object's id: >>> >>> arr = arr.sort_by { |object, otherobject| otherobject.id } >>> >>> The best way to grasp how this is works is to do it in IRB and play >>> around with the results. >> >> I just learned something new about ordering arrays! However this doesn't >> actually solve the original problem. Your solution expects both arrays >> to be properly sorted, and then keeps them together if one or the other >> is re-ordered. >> >> Originally only one of the arrays was properly sorted, and the other had >> then to be ordered to match. >> >> Here is some better sample data: >> terms = [ >> {:id=>3, :name=>"term1", :version=>2}, >> {:id=>4, :name=>"term2", :version=>2}, >> {:id=>8, :name=>"term3", :version=>1} >> ] >> >> arr2 = [ >> {:term_id=>4, :name=>"assoc1"}, >> {:term_id=>8, :name=>"assoc2"}, >> {:term_id=>3, :name=>"assoc3"} >> ] >> >> so 'terms' is properly sorted, and now we want arr2 to follow that >> order. So after our operation arr2 should look like: >> >> arr2 = [ >> {:term_id=>3, :name=>"assoc3"}, >> {:term_id=>4, :name=>"assoc1"}, >> {:term_id=>8, :name=>"assoc2"} >> >> ] >> >> These are ActiveRecord objects. A SQL solution is possible but the query >> is painfully long due to complex associations. Since the arrays are >> usually small 3-5 records, i was hoping i could just sort them >> programmatically. > > Did you try Robert Klemme's solution? Translated to this new example: > Typo: that should have been > arr2.sort_by {|o| terms.find_index {|a| o[:term_id] == a[:id]}} > > => [{:term_id=>3, :name=>"assoc3"}, {:term_id=>4, :name=>"assoc1"}, > {:term_id=>8, :name=>"assoc2"}] > > Jesus.