将一维数组转换为二维数组导致数组数值错误

3
我的一维数组正确导入并正确显示,我手动执行逻辑时也能正常工作,所以我不确定哪里出了问题。当我将1-D数组中的每个值复制到2-D数组中时,它会进行奇怪的复制模式,并放入错误的值。
这是1-D数组:
 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

这是以下输出结果:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
row:  0  col:  0
0
In loop... [[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
row:  0  col:  1
1
In loop... [[2, 0, 0, 0], [2, 0, 0, 0], [2, 0, 0, 0], [2, 0, 0, 0]]
row:  0  col:  2
2
In loop... [[3, 0, 0, 0], [3, 0, 0, 0], [3, 0, 0, 0], [3, 0, 0, 0]]
row:  0  col:  3
3
In loop... [[4, 0, 0, 0], [4, 0, 0, 0], [4, 0, 0, 0], [4, 0, 0, 0]]
row:  1  col:  0
4
In loop... [[4, 5, 0, 0], [4, 5, 0, 0], [4, 5, 0, 0], [4, 5, 0, 0]]
row:  1  col:  1
5
In loop... [[4, 6, 0, 0], [4, 6, 0, 0], [4, 6, 0, 0], [4, 6, 0, 0]]
row:  1  col:  2
6
In loop... [[4, 7, 0, 0], [4, 7, 0, 0], [4, 7, 0, 0], [4, 7, 0, 0]]
row:  1  col:  3
7
In loop... [[4, 8, 0, 0], [4, 8, 0, 0], [4, 8, 0, 0], [4, 8, 0, 0]]
row:  2  col:  0
8
In loop... [[4, 8, 9, 0], [4, 8, 9, 0], [4, 8, 9, 0], [4, 8, 9, 0]]
row:  2  col:  1
9
In loop... [[4, 8, 10, 0], [4, 8, 10, 0], [4, 8, 10, 0], [4, 8, 10, 0]]
row:  2  col:  2
10
In loop... [[4, 8, 11, 0], [4, 8, 11, 0], [4, 8, 11, 0], [4, 8, 11, 0]]
row:  2  col:  3
11
In loop... [[4, 8, 12, 0], [4, 8, 12, 0], [4, 8, 12, 0], [4, 8, 12, 0]]
row:  3  col:  0
12
In loop... [[4, 8, 12, 13], [4, 8, 12, 13], [4, 8, 12, 13], [4, 8, 12, 13]]
row:  3  col:  1
13
In loop... [[4, 8, 12, 14], [4, 8, 12, 14], [4, 8, 12, 14], [4, 8, 12, 14]]
row:  3  col:  2
14
In loop... [[4, 8, 12, 15], [4, 8, 12, 15], [4, 8, 12, 15], [4, 8, 12, 15]]
row:  3  col:  3
15
In loop... [[4, 8, 12, 16], [4, 8, 12, 16], [4, 8, 12, 16], [4, 8, 12, 16]]
Before return... [[4, 8, 12, 16], [4, 8, 12, 16], [4, 8, 12, 16], [4, 8, 12, 16]]

这是函数代码:

以下是函数的代码:

def makeTwoArr(array, height, width):
    print(array)
    newArray=[]
    line=[0]*width
    for i in range(height):
        newArray.append(line)
    location=0
    print(newArray)
    for row in range(height):
        for col in range(width):
            print("row: ",row," col: ",col);
            print(location)
##            #print(array[location])
            newArray[col][row]=array[location]
##            print(newArray)
            location+=1
            print("In loop...",newArray)

    print("Before return...",newArray)
    return newArray

我和我的计算机科学教授都无法弄清楚为什么这些值是错误的,或者为什么它在错误的迭代中填充某些位置。


尝试在newArray[col][row]=array[location]中交换colrow。我认为这样应该可以。 - Vivek Jain
1
@VivekJain 我不这么认为。 - miradulo
需要交换,但并不能解决谜团...... 赋值某种方式适用于所有行和正确的列。 - roadrunner66
而期望的输出是什么? - Francesco
一个矩阵[[1,2,3,4],[5,6,7,8],[9...可以很容易地在numpy中完成(重塑),但原帖作者想要手动完成,这应该是可行的。 - roadrunner66
@DonkeyKong,我明白你的意思了 :) - Vivek Jain
3个回答

3
当你使用line=[0]*width然后append(line)时,实际上创建了对同一行的多个引用,因此在循环中修改一行实际上会修改所有行。你需要实际地创建不同的行,以便在赋值过程中不通过在同一列表中的引用而在每个位置上修改相同的值。请记住,列表是可变的,并且添加相同的列表会创建对同一列表的引用。
另外,我猜想出于你的(教育)目的,你需要以这种循环方式进行赋值,但是如果你想更符合惯用法地使用标准库,你可以使用iterzip与解包来创建列表的列表,尽管这仅适用于您确信原始列表具有正确数量的元素的情况。这通过向zip传递相同的迭代器多次来展开整个序列来实现。
new_arr = list(map(list,zip(*[iter(arr)]*4)))

输出:

[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]

你的catch已经成功通过了我和我的教授!非常感谢! - Brandon Williams
很好,更Pythonic的方式! - Vivek Jain
@VivekJain 谢谢 :) - miradulo

2
正如Donkey Kong所说,您在引用同一行。此外,循环结构有些不正确。
def makeTwoArr(array, height, width):
    print(array)
    newArray=[[0 for x in range(width)] for x in range(height)] 
    print(newArray)
    row=0
    col=0

    # Use single loop where possible. Loop in a loop may hamper performance.
    for location in range( 0, len(array)):
        print("row: ",row," col: ",col);
        print(location)
        newArray[row][col]=array[location]
        col+=1
        if col == width:
            row+=1
            col=0
        print("In loop...",newArray)

    print("Before return...",newArray)
    return newArray

oldarr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

newarr = makeTwoArr(oldarr, 4, 4)
print "############"
print ("New Array is", newarr)

我尝试了一种不同的方法来循环源数组,而不是目标数组。原因是希望只有一个循环而不是双重循环。虽然两者都可以被视为正确的做法。请把这个解决方案当作一个起点而不是复制粘贴的解决方案。

1
我同意你和Donkey Kong的观点,感谢你以这种方式发布。我两方面都同意,但这有助于我直观地看到你的意思。不,我绝对不会只是复制和粘贴。我给你们的初始数组是我需要用于此的超级简单形式。你们的答案将帮助我理解我哪里出错了。谢谢! - Brandon Williams

0

我认为这是因为new_array中的每一行实际上都指向同一个列表line

按照以下方式更改您的代码,它应该可以正常工作:

def makeTwoArr(array, height, width):
    print(array)
    newArray=[]
    #line=[0]*width                    # DON'T DO THIS
    for i in range(height):
        newArray.append([0]*width)     # DO THIS INSTEAD
    location=0
    print(newArray)
    for row in range(height):
        for col in range(width):
            print("row: ",row," col: ",col);
            print(location)
            newArray[col][row]=array[location]
            print(newArray)
            location+=1
            print("In loop...",newArray)

    print("Before return...",newArray)
    return newArray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接