我再次尝试使这种合并排序工作。 目前,我有一个带有Unix时间码的2d数组(图1),并使用(图2)合并排序。我试图检查每个数组中的第一个值,即array [x] [0],然后根据array [x] [0]值,但是,合并排序会创建重复数据并删除其他数据(图3)。我的问题是我在做什么错?我知道这是合并排序,但看不到解决方法。
图1
[[1422403200 100]
[1462834800 150]
[1458000000 25]
[1540681200 150]
[1498863600 300]
[1540771200 100]
[1540771200 100]
[1540771200 100]
[1540771200 100]
[1540771200 100]]
图2
import numpy as np
def sort(data):
if len(data) > 1:
Mid = len(data) // 2
l = data[:Mid]
r = data[Mid:]
sort(l)
sort(r)
z = 0
x = 0
c = 0
while z < len(l) and x < len(r):
if l[z][0] < r[x][0]:
data[c] = l[z]
z += 1
else:
data[c] = r[x]
x += 1
c += 1
while z < len(l):
data[c] = l[z]
z += 1
c += 1
while x < len(r):
data[c] = r[x]
x += 1
c += 1
print(data, 'done')
unixdate = [1422403200, 1462834800, 1458000000, 1540681200, 1498863600, 1540771200, 1540771200,1540771200, 1540771200, 1540771200]
price=[100, 150, 25, 150, 300, 100, 100, 100, 100, 100]
array = np.column_stack((unixdate, price))
sort(array)
print(array, 'sorted')
图3
[[1422403200 100]
[1458000000 25]
[1458000000 25]
[1498863600 300]
[1498863600 300]
[1540771200 100]
[1540771200 100]
[1540771200 100]
[1540771200 100]
[1540771200 100]]
答案 0 :(得分:-1)
我在您的代码中找不到任何错误。
我已经尝试过您的代码,并且可以说至少在常规的Python列表中不会发生此问题:该函数不会更改列表中任何元素的出现次数。
data = [
[1422403200, 100],
[1462834800, 150],
[1458000000, 25],
[1540681200, 150],
[1498863600, 300],
[1540771200, 100],
[1540771200, 100],
[1540771200, 100],
[1540771200, 100],
[1540771200, 100],
]
sort(data)
from pprint import pprint
pprint(data)
输出:
[[1422403200, 100],
[1458000000, 25],
[1462834800, 150],
[1498863600, 300],
[1540681200, 150],
[1540771200, 100],
[1540771200, 100],
[1540771200, 100],
[1540771200, 100],
[1540771200, 100]]
编辑,要考虑到numpy上下文和 np.column_stack
的使用。
-我希望发生的情况是np.column_stack
实际上在两个数组上创建了一个 view 映射。要获得真实的数组而不是指向现有数组的链接,应copy该数组:-
array = np.column_stack((unixdate, price)).copy()
编辑2 ,并考虑到numpy上下文
此行为实际上与np.column_stack
没有关系; np.column_stack
已执行复制。
您的代码不起作用的原因是因为numpy的切片行为与python不同。切片会创建映射索引的数组的视图。
错误的行是:
l = data[:Mid]
r = data[Mid:]
由于l
和r
仅映射到data
所保存的两个内存,因此在data
被修改时会对其进行修改。这就是data[c] = l[z]
和data[c] = r[x]
行覆盖值并在移动值时创建副本的原因。
如果data
是一个numpy数组,我们希望l
和r
是数据的副本,而不仅仅是视图。这可以使用copy
方法来实现。
l = data[:Mid]
r = data[Mid:]
if isinstance(data, np.ndarray):
l = l.copy()
r = r.copy()
通过这种方式,我测试了复制的效果。
注意
如果您要使用python列表而不是numpy数组对数据进行排序,那么在香草python中,np.column_stack的等效项是zip
:
z = zip([10, 20, 30, 40], [100, 200, 300, 400], [1000, 2000, 3000, 4000])
z
# <zip at 0x7f6ef80ce8c8>
# `zip` creates an iterator, which is ready to give us our entries.
# Iterators can only be walked once, which is not the case of lists.
list(z)
# [(10, 100, 1000), (20, 200, 2000), (30, 300, 3000), (40, 400, 4000)]
条目是(非可变的)元组。如果您需要条目可编辑,请在其上列出地图:
z = zip([10, 20, 30, 40], [100, 200, 300, 400], [1000, 2000, 3000, 4000])
li = list(map(list, z))
# [[10, 100, 1000], [20, 200, 2000], [30, 300, 3000], [40, 400, 4000]]
要转置矩阵,请使用zip(*matrix)
:
def transpose(matrix):
return list(map(list, zip(*matrix)))
transpose(l)
# [[10, 20, 30, 40], [100, 200, 300, 400], [1000, 2000, 3000, 4000]]
您还可以使用li
对python列表li.sort()
进行排序,或使用sorted(li)
对任何迭代器(列表为迭代器)进行排序。
在这里,我将使用(经过测试):
sorted(zip(unixdate, price))