From: "Jesús Gabriel y Galán" Date: 2013-06-18T05:47:53+09:00 Subject: Re: Compare and sort one array according to another. 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: arr2.sort_by {|o| arr1.find_index {|a| o[:term_id] == a[:id]}} => [{:term_id=>3, :name=>"assoc3"}, {:term_id=>4, :name=>"assoc1"}, {:term_id=>8, :name=>"assoc2"}] Jesus.