简体   繁体   English

如何在2D数组中切换行和列?

[英]How do I switch rows and columns in a 2D array?

I am working on a code that will create a visual Sierpinski triangle to 3D print, and in order for it to work I have to use a Pascal triangle algorithm that will create an array so I can use to tell my algorithm that will create my triangles where not to put triangles. 我正在研究一个代码,它将为3D打印创建一个可视化的Sierpinski三角形,为了使其工作,我必须使用Pascal三角形算法来创建一个数组,这样我就可以用来告诉我的算法将创建我的三角形哪里不放三角形。

Anyway the problem is, that my code that arranges the triangles creates the triangles by column instead of by row like the Pascal algorithm does so I am just trying to do a quick fix by having a subroutine that rearranges the Pascal array. 无论如何问题是,我排列三角形的代码按列而不是像Pascal算法那样按行创建三角形,所以我只是尝试通过重新安排Pascal数组的子程序来快速修复。 I am just stumped on how to do it since I am not sure how to avoid index out of range errors. 我只是难以理解如何做到这一点,因为我不知道如何避免index out of range错误。

This is the code that creates the array for Pascal's triangle. 这是为Pascal三角形创建数组的代码。

TL:DR I am trying to make an rearrange an array where rows are the columns and columns are the rows TL:DR我正在尝试重新排列一个数组,其中行是列,列是行

def pascal(n):
    """Prints out n rows of Pascal's triangle."""
    row = [1]
    global array
    array = [[0 for x in range(int(n))] for y in range(int(n))]
    array[0]=row
    k = [0]
    for x in range(int(max(n,0)-1)):
       row=[l+r for l,r in zip(row+k,k+row)]
       array[x+1]=row
    return 1

This is the output of printing the array. 这是打印数组的输出。 I just want the rows to be columns and columns to be rows 我只想将行和列作为行

[[1],
 [1, 1],
 [1, 2, 1],
 [1, 3, 3, 1],
 [1, 4, 6, 4, 1],
 [1, 5, 10, 10, 5, 1],
 [1, 6, 15, 20, 15, 6, 1],
 [1, 7, 21, 35, 35, 21, 7, 1]]

Here is the full code if you are curious about the project, but it requires rhinoscriptsyntax to make the model. 如果您对该项目感到好奇,这里是完整的代码,但它需要rhinoscriptsyntax来制作模型。

import rhinoscriptsyntax as rhino
import math

obj = rhino.GetObject("Select object to transform", preselect=True)
scale = 3
n=math.pow(3,scale)
def pascal(n):
   """Prints out n rows of Pascal's triangle."""
   row = [1]
   global array
   array = [[0 for x in range(int(n))] for y in range(int(n))]
   array[0]=row
   k = [0]
   for x in range(int(max(n,0)-1)):
      row=[l+r for l,r in zip(row+k,k+row)]
      array[x+1]=row
   return 1
pascal(math.pow(2,scale))
print array
def remakePascal():
    pass
my_horizontalVector = [[1,0,0,6],
           [0,1,0,0],
           [0,0,1,0],
           [0,0,0,1]]

my_tsfm = [[1,0,0,0],  #identity
           [0,1,0,0],
           [0,0,1,0],
           [0,0,0,1]]


def makeTriangle(scale,obj):
    w=1/scale
    h=1/scale
    tsfm= [[w,0,0,0],   #scale about origin
            [0,h,0,0],
            [0,0,1,0],
            [0,0,0,1]]
    output= rhino.XformMultiply(my_tsfm,tsfm)
    new_obj=rhino.TransformObject(obj,output,copy=True)
    return new_obj
def placeObj(i):
    my_moveUpVector = [[1,0,0,(3/scale)*i],
           [0,1,0,(4/scale)*i],
           [0,0,1,0],
           [0,0,0,1]]
    vector = rhino.XformMultiply(my_tsfm,my_moveUpVector)
    return vector
n=0
for i in range(int(math.pow(2,scale))):
    if(i>0):
       hPlace=rhino.XformMultiply(my_tsfm,my_horizontalVector)
       obj = rhino.TransformObject(obj,hPlace)
    factor = int(math.pow(2,scale))-n
    for j in range(factor):
        if():
            pass
        else:
            Vertobj=makeTriangle(scale,obj)
            tsfm = rhino.TransformObject(Vertobj,placeObj(j),copy=True)
    n=n+1

For transposing square arrays, the simple solution is 对于转置方阵,简单的解决方案是

transposed_array = zip(*array)

This approach is not suitable for triangular data as zip does not insert padding when the rows are of unequal length. 这种方法不适用于三角形数据,因为当行长度不等时, zip不会插入填充。 itertools.izip_longest does, however: 但是, itertools.izip_longest确实如此:

import itertools
transposed_array = itertools.izip_longest(*array)

By default izip_longest pads with None , so you get results like: 默认情况下, izip_longest使用None izip_longest ,因此您可以获得如下结果:

[(1, 1, 1, 1, 1),
 (None, 1, 2, 3, 4),
 (None, None, 1, 3, 6),
 (None, None, None, 1, 4),
 (None, None, None, None, 1)]

If you wish, you can remove the None entries with a list comprehension: 如果您愿意,可以使用列表推导删除None条目:

no_nones = [[item for item in row if item is not None] for row in transposed_array]

which leaves you with: 这让你:

[[1, 1, 1, 1, 1],
 [1, 2, 3, 4],
 [1, 3, 6],
 [1, 4],
 [1]]

If you prefer to pad with 0s (or anything else), specify that as the fillvalue keyword argument to itertools.izip_longest ; 如果您希望使用0(或其他任何内容)填充,请将其指定为itertools.izip_longestfillvalue关键字参数; eg 例如

list(itertools.izip_longest(*array, fillvalue=0))

returns 回报

[(1, 1, 1, 1, 1),
 (0, 1, 2, 3, 4),
 (0, 0, 1, 3, 6),
 (0, 0, 0, 1, 4),
 (0, 0, 0, 0, 1)]

I'm assuming here that a list of tuples works for your purposes. 我在这里假设一个元组列表适用于您的目的。 If you need the inside to mutable, you can get that with a list comprehension, eg: 如果你需要内部变为可变,你可以通过列表理解得到它,例如:

list_of_lists = [list(row) for row in transposed_array]

You probably want something like this: 你可能想要这样的东西:

def pascal(n):
    a = [[int(i==0) for j in range(n)] for i in range(n)]
    for i in range(n):
        for j in range(1, 1+i):
            a[j][i] = a[j][i-1] + a[j-1][i-1]

    for line in a: print(line)

pascal(7)

this prints: 这打印:

[1, 1, 1, 1, 1, 1, 1]
[0, 1, 2, 3, 4, 5, 6]
[0, 0, 1, 3, 6, 10, 15]
[0, 0, 0, 1, 4, 10, 20]
[0, 0, 0, 0, 1, 5, 15]
[0, 0, 0, 0, 0, 1, 6]
[0, 0, 0, 0, 0, 0, 1]

You could do it as shown. 你可以这样做。 It works by first making the array square so that all the rows have the same number of elements. 它的工作原理是首先使数组成方形,以便所有行具有相同数量的元素。 then transposes the rows and columns using the built-in zip() function, and then finally removes the elements it initially added. 然后使用内置的zip()函数转置行和列,最后删除它最初添加的元素。

Note also I removed the use of the global variable array . 另请注意,我删除了全局变量array Global variables are best avoided. 最好避免使用全局变量。

from pprint import pprint

def pascal(n):
    """Creates n rows of Pascal's triangle."""
    array = [None for y in range(n)]

    row = [1]
    array[0] = row
    k = [0]
    for x in range(max(n, 0)-1):
       row = [l+r for l,r in zip(row+k, k+row)]
       array[x+1] = row

    return array

def transpose(array):
    array = array[:]  # make copy to avoid changing original
    n = len(array)
    for i, row in enumerate(array):
        array[i] = row + [None for _ in range(n - len(row))]

    array = zip(*array)

    for i, row in enumerate(array):
        array[i] = [elem for elem in row if elem is not None]

    return array

array = pascal(8)
array = transpose(array)
pprint(array)

Output: 输出:

[[1, 1, 1, 1, 1, 1, 1, 1],
 [1, 2, 3, 4, 5, 6, 7],
 [1, 3, 6, 10, 15, 21],
 [1, 4, 10, 20, 35],
 [1, 5, 15, 35],
 [1, 6, 21],
 [1, 7],
 [1]]

You can transpose the rows and columns after matching length of each rows with max row and filling with zeros. 在将每行的长度与最大行匹配并用零填充后,可以转置行和列。

Working code as below. 工作代码如下。 numpy_fillna function sourced from this SO post . numpy_fillna函数源自此SO帖子

import numpy as np
x = [[1],
 [1, 1],
 [1, 2, 1],
 [1, 3, 3, 1],
 [1, 4, 6, 4, 1],
 [1, 5, 10, 10, 5, 1],
 [1, 6, 15, 20, 15, 6, 1],
 [1, 7, 21, 35, 35, 21, 7, 1]]

a = np.array(x)

def numpy_fillna(data):
    # Get lengths of each row of data
    lens = np.array([len(i) for i in data])

    # Mask of valid places in each row
    mask = np.arange(lens.max()) < lens[:,None]

    # Setup output array and put elements from data into masked positions
    out = np.zeros(mask.shape, dtype=data.dtype)
    out[mask] = np.concatenate(data)
    return out

Result 结果

>>> numpy_fillna(a).T
array([[1, 1, 1, 1, 1, 1, 1, 1],
       [0, 1, 2, 3, 4, 5, 6, 7],
       [0, 0, 1, 3, 6, 10, 15, 21],
       [0, 0, 0, 1, 4, 10, 20, 35],
       [0, 0, 0, 0, 1, 5, 15, 35],
       [0, 0, 0, 0, 0, 1, 6, 21],
       [0, 0, 0, 0, 0, 0, 1, 7],
       [0, 0, 0, 0, 0, 0, 0, 1]], dtype=object)
>>> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM