You may want to use variation of sorting by selection where swapping would occur each time you find a 'todo' element for which its 'goal_id' attribute is equal to 'goal_id' from your array.
Todo = Struct.new(:id, :goal_id)
todos = [Todo.new(12,2), Todo.new(13,2),Todo.new(6,1), Todo.new(7,2), Todo.new(25,3), Todo.new(30,1), Todo.new(40,4)]
sort_by_this_array = [4,2,1,3]
j = 0
sort_by_this_array.each do |goal_id|
todos.each_with_index do |todo,i|
if todo.goal_id == goal_id
todos[i],todos[j] = todos[j],todos[i]
j += 1
end
end
end
I would reccommend reading some sources on the web about sorting by selection. As this is a simple variation of it http://www.sorting-algorithms.com/selection-sort
Unfortunately this solution will not preserve order of elements inside initial todos array, as each swapping changes the position on which todo element is located. So they will be sorted, but it will be not stable.
Below stable solution with additional memory.
j = 0
results = []
sort_by_this_array.each do |goal_id|
while idx = todos.index {|e| e.goal_id == goal_id}
results << todos[idx]
todos.delete_at(idx)
end
end