如何在二维数组中切换行和列?

时间:2021-07-18 04:38:45

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.

我工作在一个代码将创建一个视觉Sierpinski三角形的3 d打印,为了工作我必须使用帕斯卡三角形算法,将创建一个数组,所以我可以使用它来告诉我的算法,将创建三角形不把三角形。

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. I am just stumped on how to do it since I am not sure how to avoid index out of range errors.

不管怎样,问题是,我用来排列三角形的代码是按列创建三角形而不是按行创建的就像Pascal算法那样我只是想通过一个重新排列Pascal数组的子例程来做一个快速修复。由于我不知道如何避免索引超出范围的错误,所以我对如何做这个问题感到困惑。

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

4 个解决方案

#1


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. 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]]

#2


3  

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. itertools.izip_longest does, however:

这种方法不适用于三角形数据,因为当行长度不相等时,zip不会插入填充。itertools。然而,izip_longest做:

import itertools
transposed_array = itertools.izip_longest(*array)

By default izip_longest pads with None, so you get results like:

默认情况下,izip_最长的pad没有,所以你会得到如下结果:

[(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:

如果您愿意,您可以删除无条目与一个列表理解:

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; e.g.

如果您喜欢使用0(或其他)填充,请指定为itertools.izip_longest的fillvalue关键字参数;如。

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, e.g.:

这里我假设一个元组列表适合您的目的。如果你需要改变内部结构,你可以通过列表理解,例如:

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

#3


1  

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]

#4


0  

You can transpose the rows and columns after matching length of each rows with max row and filling with zeros.

您可以在每一行的长度与max行匹配并填充0之后转置行和列。

Working code as below. numpy_fillna function sourced from this SO post.

工作代码如下。numpy_fillna函数来源于SO post。

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)
>>> 

#1


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. 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]]

#2


3  

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. itertools.izip_longest does, however:

这种方法不适用于三角形数据,因为当行长度不相等时,zip不会插入填充。itertools。然而,izip_longest做:

import itertools
transposed_array = itertools.izip_longest(*array)

By default izip_longest pads with None, so you get results like:

默认情况下,izip_最长的pad没有,所以你会得到如下结果:

[(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:

如果您愿意,您可以删除无条目与一个列表理解:

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; e.g.

如果您喜欢使用0(或其他)填充,请指定为itertools.izip_longest的fillvalue关键字参数;如。

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, e.g.:

这里我假设一个元组列表适合您的目的。如果你需要改变内部结构,你可以通过列表理解,例如:

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

#3


1  

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]

#4


0  

You can transpose the rows and columns after matching length of each rows with max row and filling with zeros.

您可以在每一行的长度与max行匹配并填充0之后转置行和列。

Working code as below. numpy_fillna function sourced from this SO post.

工作代码如下。numpy_fillna函数来源于SO post。

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)
>>>