自定义列表遍历和修改

时间:2015-07-23 01:52:47

标签: python python-2.7

我以不寻常的顺序遍历二维列表(我的矩阵表示):从左上角的元素开始逆时针绕着外部。

我需要不止一次这样做,但每次我这样做,我都想做一些与我遇到的价值不同的事情。第一次,我想记下这些值,以便我可以修改它们。 (我无法在适当的位置修改它们。)第二次,我想遍历矩阵的外部并按照我的方式修改矩阵的值,也许从某个生成器获取我的新值。

有没有办法可以将这个遍历抽象为一个函数并仍然实现我的目标?我在想这个遍历边缘函数可以使用函数和矩阵,并将函数应用于矩阵边缘上的每个元素。但是,这个问题是双重的。如果我这样做,我不认为我可以修改作为参数给出的矩阵,并且我不能逐一产生这些值,因为yield isn' ta函数。 / p>

编辑:我想逆时针旋转矩阵(不是90度),其中一个旋转移动,例如,左上角元素向下移动一个点。要做到这一点,我要旋转一个"等级"一次(或壳)矩阵。因此,如果我旋转最外层,我想遍历它一次以建立一个我可以向左移动的列表,然后我想再次遍历最外层以为它分配我计算的那些新值。 / p>

4 个答案:

答案 0 :(得分:1)

只需创建4个循环,每个循环一个数组,用于计算该方面更改的索引值。例如,x索引始终为0的第一个边可以将y从0变为n-2(从左上角到左下角的shy);重复另一方。

答案 1 :(得分:1)

我认为您可以采取两种方法来解决问题。

第一个选项是创建一个函数,该函数将可迭代的索引返回到矩阵中。然后你用for循环在矩阵上写下你的各种传递:

for i, j in matrix_border_index_gen(len(matrix), len(matrix[0])): # pass in dimensions
    # do something with matrix[i][j]

另一种选择是编写一个更像map的函数,它将给定函数依次应用于矩阵的每个适当值。如果您有时需要用新的值替换当前值,我建议您一直这样做(当您不想替换值时,您可以让您的函数返回之前的值) ):

def func(value):
    # do stuff with value from matrix
    return new_value # new_value can be the same value, if you don't want to change it

matrix_border_map(func, matrix) # replace each value on border of matrix with func(value)

答案 2 :(得分:1)

我在这里添加了几行python 3代码。它具有镜像功能和螺旋迭代器(不确定,如果这是你的意思)。没有doc字符串(抱歉)。虽然它是可读的。更改python 2的打印语句。

编辑:修复了一个错误

class Matrix():

    def __init__(self, rows=5, cols=5):
        self.cells = [[None for c in range(cols)] for r in range(rows)]

    def transpose(self):
        self.cells = list(map(list, zip(*self.cells)))

    def mirror(self):
        for row in self.cells:
            row.reverse()

    def invert(self):
        self.cells.reverse()

    def rotate(self, clockwise=True):
        self.transpose()
        self.mirror() if clockwise else self.invert()

    def iter_spiral(self, grid=None):
        grid = grid or self.cells
        next_grid = []
        for cell in reversed(grid[0]):
            yield cell
        for row in grid[1:-1]:
            yield row[0]
            next_grid.append(row[1:-1])
        if len(grid) > 1:
            for cell in grid[-1]:
                yield cell
        for row in reversed(grid[1:-1]):
            yield row[-1]
        if next_grid:
            for cell in self.iter_spiral(grid=next_grid):
                yield cell

    def show(self):
        for row in self.cells:
            print(row)

def test_matrix():
    m = Matrix()
    m.cells = [[1,2,3,4],
               [5,6,7,8],
               [9,10,11,12],
               [13,14,15,16]]
    print("We expect the spiral to be:", "4, 3, 2, 1, 5, 9, 13, 14, 15, 16, 12, 8, 7, 6, 10, 11", sep='\n')
    print("What the iterator yields:")
    for cell in m.iter_spiral():
        print(cell, end=', ')
    print("\nThe matrix looks like this:")
    m.show()
    print("Now this is how it looks rotated 90 deg clockwise")
    m.rotate()
    m.show()
    print("Now we'll rotate it back")
    m.rotate(clockwise=False)
    m.show()
    print("Now we'll transpose it")
    m.transpose()
    m.show()
    print("Inverting the above")
    m.invert()
    m.show()
    print("Mirroring the above")
    m.mirror()
    m.show()

if __name__ == '__main__':
    test_matrix()

这是输出:

We expect the spiral to be:
4, 3, 2, 1, 5, 9, 13, 14, 15, 16, 12, 8, 7, 6, 10, 11
What the iterator yields:
4, 3, 2, 1, 5, 9, 13, 14, 15, 16, 12, 8, 7, 6, 10, 11, 
The matrix looks like this:
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
[13, 14, 15, 16]
Now this is how it looks rotated 90 deg clockwise
[13, 9, 5, 1]
[14, 10, 6, 2]
[15, 11, 7, 3]
[16, 12, 8, 4]
Now we'll rotate it back
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
[13, 14, 15, 16]
Now we'll transpose it
[1, 5, 9, 13]
[2, 6, 10, 14]
[3, 7, 11, 15]
[4, 8, 12, 16]
Inverting the above
[4, 8, 12, 16]
[3, 7, 11, 15]
[2, 6, 10, 14]
[1, 5, 9, 13]
Mirroring the above
[16, 12, 8, 4]
[15, 11, 7, 3]
[14, 10, 6, 2]
[13, 9, 5, 1]

答案 3 :(得分:0)

我会选择generator functions。它们可用于创建我们可以迭代的迭代器。生成器函数的示例 -

def genfunc():
    i = 0
    while i < 10:
            yield i
            i = i + 1

>>> for x in genfunc():
...     print(x)
...
0
1
2
3
4
5
6
7
8
9

调用生成器函数时,它返回一个生成器对象 -

>>> genfunc()
<generator object genfunc at 0x00553AD0>

此时不会开始检查该功能。当你开始遍历生成器对象,调用它的第一个元素时,它开始遍历函数,直到它到达第一个yield语句,然后它返回值(在上面的例子中,它返回值{{1 })。并且它还保存了该点的函数状态(即它保存了在生成值时执行的时间点,本地命名空间中变量的值等等)。

然后当它试图获得下一个值时,再次执行从上次停止的位置开始,直到它再次产生另一个值。这种情况还在继续。