You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

numpy数组元素同步变更及Tim Sort排序HDF5数组异常问题

问题解答

问题1:numpy数组元素与列表元素同步变更问题

为何将2D numpy数组中的元素追加到列表后,修改原数组对应元素时,列表中的元素也会同步发生变化?

原因

numpy结构化数组(或对象数组)的单个元素本质是对原数组内存区域的引用/视图,而非独立副本。当你将数组元素追加到列表时,列表中存储的是该元素的引用,而非数据的拷贝。因此,修改原数组中的元素时,实际上是在修改同一个内存地址中的数据,列表里的元素自然会同步变化。

解决办法

如果需要避免这种同步变更,在将元素追加到列表前,创建元素的副本:

left.append(array[l + i].copy())  # 对单个元素创建副本
# 或者直接对切片创建副本
left = array[l:m+1].copy().tolist()

问题2:Tim Sort排序HDF5转numpy数组异常问题

尝试使用稳定排序算法Tim Sort对HDF5文件数据进行排序,已将HDF5文件中的数据转换为2D numpy数组,插入排序步骤执行正常,但调试时发现,在合并阶段将预排序的left或right数组元素逐一赋值给原数组时,left和right数组也会被修改,导致整个数据块内仅重复出现单个元素,排序逻辑被打乱,无法得到正确的排序结果。

异常原因

问题根源和问题1完全一致:在merge函数中,left和right列表直接追加了原numpy数组的元素引用,而非独立副本。当执行array[k] = left[i]或array[k] = right[j]时,若k的位置属于left或right对应的原数组区间,修改array[k]会同时改变left或right列表中对应位置的元素(因为它们指向同一块内存)。后续合并时,left/right的元素已经被篡改,最终导致所有元素被覆盖为同一个值。

修复后的代码

修改merge函数,创建left和right时使用元素副本:

from collections import deque
import h5py
import sys

filename = sys.argv[1]

with h5py.File(filename, "r") as f:
    a_group_key = list(f.keys())[0]
    ds_arr = f[a_group_key][()]

MINIMUM= 32
  
def find_minrun(n): 
    r = 0
    while n >= MINIMUM: 
        r |= n & 1
        n >>= 1
    return n + r 
  
def insertion_sort(array, left, right): 
    for i in range(left+1,right+1):
        j = i
        while array[j-1][11]>array[j][11] and j>left :
            array[[j, j-1]] = array[[j-1, j]]
            j -= 1
    return array
              
def merge(array, l, m, r): 
    array_length1= m - l + 1
    array_length2 = r - m 
    left = []
    right = []
    # 关键修改:创建元素副本而非直接引用
    for i in range(0, array_length1): 
        left.append(array[l + i].copy()) 
    for i in range(0, array_length2): 
        right.append(array[m + 1 + i].copy()) 
  
    i=0
    j=0
    k=l
   
    while j < array_length2 and  i < array_length1: 
        if left[i][11] <= right[j][11]:
            array[k] = left[i]
            i += 1
  
        else: 
            array[k] = right[j]
            j += 1
  
        k += 1
  
    while i < array_length1: 
        array[k] = left[i] 
        k += 1
        i += 1
  
    while j < array_length2: 
        array[k] = right[j] 
        k += 1
        j += 1
  
def tim_sort(array): 
    n = len(array) 
    minrun = find_minrun(n) 
  
    for start in range(0, n, minrun): 
        end = min(start + minrun - 1, n - 1) 
        insertion_sort(array, start, end) 
   
    size = minrun 
    while size < n: 
        # 修正变量名冲突:原循环变量名与merge函数内的left列表重名
        for left_idx in range(0, n, 2 * size): 
            mid = min(n - 1, left_idx + size - 1) 
            right_idx = min((left_idx + 2 * size - 1), (n - 1)) 
            merge(array, left_idx, mid, right_idx) 
        size = 2 * size 

tim_sort(ds_arr)

额外说明:原代码中tim_sort函数的循环变量名left与merge函数内的left列表重名,虽不影响运行但易造成混淆,已修改为left_idx。

效果验证

修复后,left和right列表存储的是独立副本,修改原数组时不会篡改这两个列表的内容,合并阶段能正常比较元素值,最终得到正确的排序结果。


内容的提问来源于stack exchange,提问作者Prajjwal Das

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:31:34