Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python内置中使用swap方法而不是ai,aj=aj,ai进行排序_Python_Sorting - Fatal编程技术网

如何在Python内置中使用swap方法而不是ai,aj=aj,ai进行排序

如何在Python内置中使用swap方法而不是ai,aj=aj,ai进行排序,python,sorting,Python,Sorting,我有一个需要排序的对象,但尽管它有可排序属性的索引,但它不是一个列表。相反,它有一个swap方法。有办法把它分类吗 我的想法是使用一个单独的列表并跟踪排序所需的步骤,这样我就可以将每个交换应用于对象,但我不知道应该重载什么 也就是说,大多数(所有?)排序算法内部都有一个交换行,如下所示: my_list[i], my_list[j] = my_list[j], my_list[i] class SwappableList(list): def swap(self, i, j):

我有一个需要排序的对象,但尽管它有可排序属性的索引,但它不是一个
列表。相反,它有一个
swap
方法。有办法把它分类吗

我的想法是使用一个单独的列表并跟踪排序所需的步骤,这样我就可以将每个交换应用于对象,但我不知道应该重载什么

也就是说,大多数(所有?)排序算法内部都有一个交换行,如下所示:

my_list[i], my_list[j] = my_list[j], my_list[i]
class SwappableList(list):
    def swap(self, i, j):
        self[i], self[j] = self[j], self[i]

s = SwappableList("bcdefahg")
print(f"before: {''.join(s)}") # prints "before: bcdefahg"
sort_with_swap(s)
print(f"after:  {''.join(s)}") # prints "after:  abcdefgh"
我想得到所有
(I,j)
对的集合

我不想自己重新实现sort

更新:使用快速排序实现,我得到了一些有用的东西:

def partition(array, begin, end):
    pivot = begin
    for i in range(begin+1, end+1):
        if array[i] <= array[begin]:
            pivot += 1
            #array[i], array[pivot] = array[pivot], array[i]
            array.swap(i, pivot)
    #array[pivot], array[begin] = array[begin], array[pivot]
    array.swap(pivot, begin)
    return pivot

def quicksort(array, begin=0, end=None):
    if end is None:
        end = len(array) - 1
    def _quicksort(array, begin, end):
        if begin >= end:
            return
        pivot = partition(array, begin, end)
        _quicksort(array, begin, pivot-1)
        _quicksort(array, pivot+1, end)
    return _quicksort(array, begin, end)


class SwapSorter(list):
    def __init__(self, array, obj):
        super().__init__(array)
        self._obj = obj

    def swap(self, i, j):
        if i == j: return
        print("swapping:",i,j)
        self[i], self[j] = self[j], self[i]
        self._obj.swap(i,j)


ss = SwapSorter(array, obj)
quicksort(ss)

print("sorted:")
print(ss)
print(ss._obj)
def分区(数组、开始、结束):
枢轴=开始
对于范围内的i(开始+1,结束+1):
如果数组[i]=结束:
返回
pivot=分区(数组、开始、结束)
_快速排序(数组、开始、pivot-1)
_快速排序(数组,轴+1,结束)
返回\u快速排序(数组、开始、结束)
类交换器(列表):
定义初始化(自、数组、对象):
super().\uuuu init\uuuu(数组)
自身。_obj=obj
def交换(自身、i、j):
如果i==j:返回
打印(“交换:”,i,j)
self[i],self[j]=self[j],self[i]
自交换(i,j)
ss=SwapSorter(阵列,obj)
快速排序(ss)
打印(“已排序:”)
印刷品(ss)
打印(ss.\U obj)
但是(我想)我只想使用内置排序而不是我自己的排序。。。或者,这只是一种常见的做法,您可以自己进行分类吗?

实际答案是 听起来你所做的很好,但我很好奇,并根据你所问的精神想出了一个答案。有关动机及其工作原理,请参见后面的章节,但切中要害:

def sort_with_swap(mylist):
    # Source locations of items (satifies: source_index = source_indices[dest_index])
    source_indices = sorted(range(len(mylist)), key=lambda i: mylist[i])

    # Destination locations of items (satisfies: dest_index = destination_indices[source_index])
    destination_indices = [None] * len(source_indices)
    for dest_index, source_index in enumerate(source_indices):
        destination_indices[source_index] = dest_index

    # Perform the swaps
    for dest_index, source_index in enumerate(source_indices):
        # Nothing to do if src==dest (although code below actually works if you remove this)
        if source_index == dest_index:
            continue

        # Swap the source item into the correct destination
        mylist.swap(source_index, dest_index)

        # Update the index lists for the new location of the item that had been in the destination
        old_dest_at_dest_index = destination_indices[dest_index]
        source_indices[old_dest_at_dest_index] = source_index
        destination_indices[source_index] = old_dest_at_dest_index

        # These two updates are not necessary but leave index lists in correct state at the end
        # source_indices[dest_index] = dest_index
        # destination_indices[dest_index] = dest_index
测试 您可以尝试以下功能:

my_list[i], my_list[j] = my_list[j], my_list[i]
class SwappableList(list):
    def swap(self, i, j):
        self[i], self[j] = self[j], self[i]

s = SwappableList("bcdefahg")
print(f"before: {''.join(s)}") # prints "before: bcdefahg"
sort_with_swap(s)
print(f"after:  {''.join(s)}") # prints "after:  abcdefgh"
动机 我认为您的问题建议跟踪排序时交换的内容,并直接对列表执行这些交换。正如你所看到的,我采取了一种不同的策略:允许整个排序在索引列表上进行,然后在此基础上进行交换。这有几个好处:

  • 这样就不那么麻烦了,因为要跟踪这类任务发生时正在执行的操作,您必须等待两个任务,检查它们是否真的是交换,然后将它们重新缝合在一起
  • 如果排序实现执行与交换不同的操作(例如,排列三个元素,或将透视项保留在单独的位置),它不会中断
  • 它减少了列表式结构上的掉期数量,听起来可能很昂贵
  • 工作原理 这是我第一次天真地尝试我的想法:

    # Warning: doesn't work
    def sort_with_swap_naive(mylist):
        source_indices = sorted(range(len(mylist)), key=lambda i: mylist[i])
        for dest_index, source_index in enumerate(source_indices):
            mylist.swap(source_index, dest_index)
    
    这很简单:

  • 我们对索引列表而不是原始列表进行排序。例如,对于
    列表('bcdefahg')
    ,您会得到
    [5,0,1,2,3,4,7,6]
  • 我们浏览索引列表,并将每个项交换到正确的位置
  • 不幸的是,这个简单的版本不起作用。首先,如果您通过最后两项(
    'g'
    'h'
    )跟踪交换,您会发现我们将它们交换到正确的位置,并立即将它们交换回来!对于列表的置换部分,问题更为复杂,但潜在的问题是相同的

    问题是:我们正在使用off
    源代码索引来确定要交换哪些元素,但是当我们浏览列表时,它就不同步了。为了解决这个问题,我们还需要在进行掉期交易时对其进行更新。事实证明,为了有效地实现这一点,我们需要一个包含相反映射的列表,即目的地索引列表。要查看需要更新的内容,请查看交换元素0和5前后的原始列表:

    mylist = ['b', 'c', 'd', 'e', 'f', 'a', 'h', 'g']
    sources = [5, 0, 1, 2, 3, 4, 7, 6]
    destinations = [1, 2, 3, 4, 5, 0, 7, 6]
    
    # Swap item at 0 with item at 5
    mylist = ['a', 'c', 'd', 'e', 'f', 'b', 'h', 'g']
    # updates:      ^                   ^
    sources = [0, 5, 1, 2, 3, 4, 7, 6]
    # updates: ^  ^
    destinations = [0, 2, 3, 4, 5, 1, 7, 6]
    # updates:      ^              ^
    
    正如您所看到的(可能!),要更新的关键内容是在交换前立即位于目标索引(即位于0的“b”)的项。

    实际答案 听起来你所做的很好,但我很好奇,并根据你所问的精神想出了一个答案。有关动机及其工作原理,请参见后面的章节,但切中要害:

    def sort_with_swap(mylist):
        # Source locations of items (satifies: source_index = source_indices[dest_index])
        source_indices = sorted(range(len(mylist)), key=lambda i: mylist[i])
    
        # Destination locations of items (satisfies: dest_index = destination_indices[source_index])
        destination_indices = [None] * len(source_indices)
        for dest_index, source_index in enumerate(source_indices):
            destination_indices[source_index] = dest_index
    
        # Perform the swaps
        for dest_index, source_index in enumerate(source_indices):
            # Nothing to do if src==dest (although code below actually works if you remove this)
            if source_index == dest_index:
                continue
    
            # Swap the source item into the correct destination
            mylist.swap(source_index, dest_index)
    
            # Update the index lists for the new location of the item that had been in the destination
            old_dest_at_dest_index = destination_indices[dest_index]
            source_indices[old_dest_at_dest_index] = source_index
            destination_indices[source_index] = old_dest_at_dest_index
    
            # These two updates are not necessary but leave index lists in correct state at the end
            # source_indices[dest_index] = dest_index
            # destination_indices[dest_index] = dest_index
    
    测试 您可以尝试以下功能:

    my_list[i], my_list[j] = my_list[j], my_list[i]
    
    class SwappableList(list):
        def swap(self, i, j):
            self[i], self[j] = self[j], self[i]
    
    s = SwappableList("bcdefahg")
    print(f"before: {''.join(s)}") # prints "before: bcdefahg"
    sort_with_swap(s)
    print(f"after:  {''.join(s)}") # prints "after:  abcdefgh"
    
    动机 我认为您的问题建议跟踪排序时交换的内容,并直接对列表执行这些交换。正如你所看到的,我采取了一种不同的策略:允许整个排序在索引列表上进行,然后在此基础上进行交换。这有几个好处:

  • 这样就不那么麻烦了,因为要跟踪这类任务发生时正在执行的操作,您必须等待两个任务,检查它们是否真的是交换,然后将它们重新缝合在一起
  • 如果排序实现执行与交换不同的操作(例如,排列三个元素,或将透视项保留在单独的位置),它不会中断
  • 它减少了列表式结构上的掉期数量,听起来可能很昂贵
  • 工作原理 这是我第一次天真地尝试我的想法:

    # Warning: doesn't work
    def sort_with_swap_naive(mylist):
        source_indices = sorted(range(len(mylist)), key=lambda i: mylist[i])
        for dest_index, source_index in enumerate(source_indices):
            mylist.swap(source_index, dest_index)
    
    这很简单:

  • 我们对索引列表而不是原始列表进行排序。例如,对于
    列表('bcdefahg')
    ,您会得到
    [5,0,1,2,3,4,7,6]
  • 我们浏览索引列表,并将每个项交换到正确的位置
  • 不幸的是,这个简单的版本不起作用。首先,如果您通过最后两项(
    'g'
    'h'
    )跟踪交换,您会发现我们将它们交换到正确的位置,并立即将它们交换回来!对于列表的置换部分,问题更为复杂,但潜在的问题是相同的

    问题是:我们正在使用off
    源代码索引来确定要交换哪些元素,但是当我们浏览列表时,它就不同步了。为了解决这个问题,我们还需要在进行掉期交易时对其进行更新。事实证明,要做到这一点