在Python中使用归并排序基于数字值对数组数组进行排序的逻辑澄清?

huangapple go评论62阅读模式
英文:

Logic Clarification for sorting an array of array in python based off the value of a number using merge sort?

问题

我想根据每个内部数组中的最后一个数字,从最高值到最低值对数组中的数组进行归并排序:

arraySample=[['a', 'new', 3], ['a', 'new', 3],  ['b', 'new', 1], ['c', 'old', 2], ['c', 'old', 2], ['d', 'new', 1],['a', 'new', 3],['e', 'old', 3],['e', 'old', 3],['e', 'old', 3]]

此外,我希望确保按照相同名称的元素仍然按顺序排列。

即使现在有以下代码和底部的输出:

# 归并
def merge(arr1, arr2, index):
    arr3 = []
    sizeA = len(arr1)
    sizeB = len(arr2)

    indexa = indexb = 0

    while indexa < sizeA and indexb < sizeB:
        if arr1[indexa][index] >= arr2[indexb][index]:
            arr3.append(arr1[indexa])
            indexa += 1
        else:
            arr3.append(arr2[indexb])
            indexb += 1

    arr3.extend(arr1[indexa:sizeA])
    arr3.extend(arr2[indexb:sizeB])
    return arr3

# 归并排序
def mergesort(array, index=-1):
    size = len(array)

    if size == 1:
        return array

    midindex = size // 2
    firsthalf = array[0:midindex]
    secondhalf = array[midindex:size]

    firsthalf = mergesort(firsthalf, index)
    secondhalf = mergesort(secondhalf, index)
    array = merge(firsthalf, secondhalf, index)

    return array

mergesort(arraySample)
for i in arraySample:
    print(str(i)+"\n")

输出是:

['a', 'new', 3]

['a', 'new', 3]

['b', 'new', 1]

['c', 'old', 2]

['c', 'old', 2]

['d', 'new', 1]

['a', 'new', 3]

['e', 'old', 3]

['e', 'old', 3]

['e', 'old', 3]

但是预期输出是:

['a', 'new', 3]

['a', 'new', 3]

['a', 'old', 3]

['e', 'old', 3]

['e', 'new', 3]

['e', 'old', 3]

['c', 'old', 2]

['c', 'old', 2]

['b', 'new', 1]

['d', 'new', 1]

您可以通过更改归并函数的方式来解决此问题。以下是更新的代码:

# 归并
def merge(arr1, arr2, index):
    arr3 = []
    sizeA = len(arr1)
    sizeB = len(arr2)

    indexa = indexb = 0

    while indexa < sizeA and indexb < sizeB:
        if arr1[indexa][index] >= arr2[indexb][index]:
            arr3.append(arr1[indexa])
            indexa += 1
        else:
            arr3.append(arr2[indexb])
            indexb += 1

    # 在合并后,将相同名称的元素再次排序
    while indexa < sizeA:
        arr3.append(arr1[indexa])
        indexa += 1

    while indexb < sizeB:
        arr3.append(arr2[indexb])
        indexb += 1

    return arr3

# 归并排序
def mergesort(array, index=-1):
    size = len(array)

    if size == 1:
        return array

    midindex = size // 2
    firsthalf = array[0:midindex]
    secondhalf = array[midindex:size]

    firsthalf = mergesort(firsthalf, index)
    secondhalf = mergesort(secondhalf, index)
    array = merge(firsthalf, secondhalf, index)

    return array

mergesort(arraySample, index=0)  # 使用第一个元素(名称)进行排序
for i in arraySample:
    print(str(i)+"\n")

这将按照名称进行排序,并产生您期望的输出。

英文:

I want to sort an array of array with merge sort based off the last number in each internal array from highest value to lowest value:

arraySample=[[&#39;a&#39;, &#39;new&#39;, 3], [&#39;a&#39;, &#39;new&#39;, 3],  [&#39;b&#39;, &#39;new&#39;, 1], [&#39;c&#39;, &#39;old&#39;, 2], [&#39;c&#39;, &#39;old&#39;, 2], [&#39;d&#39;, &#39;new&#39;, 1],[&#39;a&#39;, &#39;new&#39;, 3],[&#39;e&#39;, &#39;old&#39;, 3],[&#39;e&#39;, &#39;old&#39;, 3],[&#39;e&#39;, &#39;old&#39;, 3]]

In addition , I want to make sure that it is also sorted in a way such that the elements with the same name should still be ordered together .

I.e the 3 elements of 'a' should be ordered together , followed by the 3 elements of 'e' etc..

For now here is the code I have and at the bottom is the output:

Merge

def merge(arr1, arr2, index):
    arr3 = []
    sizeA = len(arr1)
    sizeB = len(arr2)

    indexa = indexb = 0

    while indexa &lt; sizeA and indexb &lt; sizeB:
        if arr1[indexa][index] &gt;= arr2[indexb][index]:
            arr3.append(arr1[indexa])
            indexa += 1
        else:
            arr3.append(arr2[indexb])
            indexb += 1

    arr3.extend(arr1[indexa:sizeA])
    arr3.extend(arr2[indexb:sizeB])
    return arr3

Merge Sort

def mergesort(array, index=-1):
    size = len(array)

    if size == 1:
        return array

    midindex = size // 2
    firsthalf = array[0:midindex]
    secondhalf = array[midindex:size]

    firsthalf = mergesort(firsthalf, index)
    secondhalf = mergesort(secondhalf, index)
    array = merge(firsthalf, secondhalf, index)

    return array
mergesort(arraySample)
for i in arraySample:
    print(str(i)+&quot;\n&quot;)

Output

[&#39;a&#39;, &#39;new&#39;, 3]

[&#39;a&#39;, &#39;new&#39;, 3]

[&#39;b&#39;, &#39;new&#39;, 1]

[&#39;c&#39;, &#39;old&#39;, 2]

[&#39;c&#39;, &#39;old&#39;, 2]

[&#39;d&#39;, &#39;new&#39;, 1]

[&#39;a&#39;, &#39;new&#39;, 3]

[&#39;e&#39;, &#39;old&#39;, 3]

[&#39;e&#39;, &#39;old&#39;, 3]

[&#39;e&#39;, &#39;old&#39;, 3]

However the expected output is:

[&#39;a&#39;, &#39;new&#39;, 3]

[&#39;a&#39;, &#39;new&#39;, 3]

[&#39;a&#39;, &#39;old&#39;, 3]

[&#39;e&#39;, &#39;old&#39;, 3]

[&#39;e&#39;, &#39;new&#39;, 3]

[&#39;e&#39;, &#39;old&#39;, 3] 

[&#39;c&#39;, &#39;old&#39;, 2]

[&#39;c&#39;, &#39;old&#39;, 2]

[&#39;b&#39;, &#39;new&#39;, 1]

[&#39;d&#39;, &#39;new&#39;, 1]

May I know how could improve or change the code to solve this issue? I am a beginner to Data Structures and Algorithms but I am trying to learn. Please note that I am trying to avoid the usage of external methods and libraries as well as in-built methods. Thank you !

答案1

得分: 1

你的代码目前使用 index 来确定项目的排序方式,而你使用 -1(默认值)来表示它。但是,由于你希望将第一个成员(名称)加入到排序逻辑中,你需要传递更多的信息。可以是第二个索引(这将是 0),但也许最好是将一个关键的 函数 作为参数传递。然后让该函数返回一个值(元组),用于确定给定元素的顺序。

请注意,排序后的列表由你的 mergesort 函数返回,因此主要代码应该捕获返回的列表。

以下是使用这个想法更新的代码:

def merge(arr1, arr2, key):  # 接受一个关键函数作为参数
    arr3 = []
    sizeA = len(arr1)
    sizeB = len(arr2)

    indexa = indexb = 0

    while indexa < sizeA and indexb < sizeB:
        if key(arr1[indexa]) < key(arr2[indexb]):  # 调用关键函数来确定顺序
            arr3.append(arr1[indexa])
            indexa += 1
        else:
            arr3.append(arr2[indexb])
            indexb += 1

    arr3.extend(arr1[indexa:])
    arr3.extend(arr2[indexb:])
    return arr3

def mergesort(array, key):
    size = len(array)

    if size == 1:
        return array

    midindex = size // 2
    firsthalf = array[0:midindex]
    secondhalf = array[midindex:size]

    firsthalf = mergesort(firsthalf, key)
    secondhalf = mergesort(secondhalf, key)
    array = merge(firsthalf, secondhalf, key)

    return array

arraySample = [['a', 'new', 3], ['e', 'old', 3], ['a', 'new', 3], ['b', 'new', 1], ['c', 'old', 2], ['c', 'old', 2], ['d', 'new', 1], ['a', 'new', 3], ['e', 'old', 3], ['e', 'old', 3]]

# 传递一个关键函数:
#    按第2个成员降序排列: `-a[2]`
#    按第0个成员升序排列: `a[0]`

result = mergesort(arraySample, lambda a: (-a[2], a[0]))

for elem in result:
    print(elem)
英文:

Your code currently uses index to determine how items should be ordered, and you use -1 (the default) for it. But as you want to add the first member (name) into the order logic, you need to pass along more information. It could be a second index (which would be 0), but maybe it is better to pass a key function as argument. Then let that function return a value (a tuple) that determines the order of the given element.

Note that the sorted list is returned by your mergesort function, so the main code should capture that returned list.

Here is your code updated with that idea:

def merge(arr1, arr2, key):  # takes a key argument
    arr3 = []
    sizeA = len(arr1)
    sizeB = len(arr2)

    indexa = indexb = 0

    while indexa &lt; sizeA and indexb &lt; sizeB:
        if key(arr1[indexa]) &lt; key(arr2[indexb]):  # call key to determine order
            arr3.append(arr1[indexa])
            indexa += 1
        else:
            arr3.append(arr2[indexb])
            indexb += 1

    arr3.extend(arr1[indexa:])
    arr3.extend(arr2[indexb:])
    return arr3

def mergesort(array, key):
    size = len(array)

    if size == 1:
        return array

    midindex = size // 2
    firsthalf = array[0:midindex]
    secondhalf = array[midindex:size]

    firsthalf = mergesort(firsthalf, key)
    secondhalf = mergesort(secondhalf, key)
    array = merge(firsthalf, secondhalf, key)

    return array

arraySample=[[&#39;a&#39;, &#39;new&#39;, 3], [&#39;e&#39;, &#39;old&#39;, 3],[&#39;a&#39;, &#39;new&#39;, 3],  [&#39;b&#39;, &#39;new&#39;, 1], [&#39;c&#39;, &#39;old&#39;, 2], [&#39;c&#39;, &#39;old&#39;, 2], [&#39;d&#39;, &#39;new&#39;, 1],[&#39;a&#39;, &#39;new&#39;, 3],[&#39;e&#39;, &#39;old&#39;, 3],[&#39;e&#39;, &#39;old&#39;, 3]]

# Pass a key function:
#    descending by member 2: `-a[2]`
#    ascending by member 0: `a[0]`

result = mergesort(arraySample, lambda a: (-a[2], a[0]))

for elem in result:
    print(elem)

huangapple
  • 本文由 发表于 2023年6月22日 12:51:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76528686.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定