Using Python's built-in sort with custom swap function instead of list element exchange

I’m working with a custom object that needs sorting but it’s not a standard list type. The object has indexed elements with sortable values and provides a swap method for element exchange.

Instead of the typical element swapping pattern:

data[x], data[y] = data[y], data[x]

I need to use the object’s swap method. I want to leverage Python’s built-in sorting rather than implementing my own algorithm.

I tried creating a wrapper approach with bubble sort:

def bubble_sort_with_swap(arr, start, finish):
    pivot_point = start
    for index in range(start + 1, finish + 1):
        if arr[index] <= arr[start]:
            pivot_point += 1
            arr.exchange(index, pivot_point)
    arr.exchange(pivot_point, start)
    return pivot_point

def sort_recursive(arr, start=0, finish=None):
    if finish is None:
        finish = len(arr) - 1
    
    def _sort_helper(arr, start, finish):
        if start >= finish:
            return
        pivot = bubble_sort_with_swap(arr, start, finish)
        _sort_helper(arr, start, pivot - 1)
        _sort_helper(arr, pivot + 1, finish)
    
    return _sort_helper(arr, start, finish)

class CustomSwapper(list):
    def __init__(self, data, target_obj):
        super().__init__(data)
        self._target = target_obj
    
    def exchange(self, pos1, pos2):
        if pos1 == pos2: 
            return
        self[pos1], self[pos2] = self[pos2], self[pos1]
        self._target.exchange(pos1, pos2)

wrapper = CustomSwapper(my_data, my_object)
sort_recursive(wrapper)

Is there a way to make Python’s built-in sort work with custom swap operations, or should I stick with custom sorting implementations?

Python’s built-in sort assumes direct element access, which your custom object breaks. But there’s a middle-ground that works better than rolling your own sorting.

Try a permutation-based approach. Let Python sort normally on a separate structure, then apply that permutation to your custom object using its swap method. You keep Timsort’s efficiency while working within your swap constraints.

I’ve done this with memory-mapped data that had similar swap-only interfaces. Create an index array, sort it based on your comparison criteria, then calculate the minimal swaps needed for that ordering. Any permutation breaks down into cycles, and you can apply those cycles through your swap method.

You get the best of both worlds - Python’s optimized sorting to determine the correct order, plus proper integration with your object’s swap interface. The overhead beats implementing quicksort or mergesort from scratch.

Python’s built-in sort is super optimized but it’s built for element assignment, not custom swap methods. You can’t hook into its swap operations directly.

Your wrapper idea works, but why rebuild sorting from scratch? Here’s something cleaner:

class SortableWrapper:
    def __init__(self, obj):
        self.obj = obj
        self.data = list(obj)  # assuming your object is iterable
    
    def sort_and_apply(self):
        # Get sorted indices
        indices = sorted(range(len(self.data)), key=lambda i: self.data[i])
        
        # Apply swaps to reach sorted state
        for i, target_pos in enumerate(indices):
            if i != target_pos:
                self.obj.swap(i, target_pos)
                # Update our tracking
                indices[indices.index(i)] = target_pos

That said, this whole sorting coordination thing screams automation to me. I’ve dealt with similar data transformation headaches by building automated workflows that handle the sorting logic and apply operations systematically.

Why fight Python’s sorting limitations when you could automate the whole thing? Build a workflow that handles your custom object sorting, tracks operations, and applies them in the right order. Scales way better with multiple custom objects or complex sorting needs.