Python- IndexError:列表索引超出范围,而在for循环中

时间:2019-09-28 13:34:34

标签: python python-3.x for-loop multidimensional-array pycharm

我是python的新手。我正在尝试编写代码以从文本文件中获取输入,例如

6 6
* o o o o *
o o * o o o
o o * o o *
o o * o o o
o o o o * o
o o o o o o

计算每个字符串附近的“ *”数,并使用新的计数更新每个字符串,例如:

6 6
* 2 1 1 1 *
1 3 * 2 2 2
0 3 * 3 1 *
0 2 * 2 2 2
0 1 1 2 * 1
0 0 0 1 1 1

并在output.txt上更新它。到目前为止,我的代码一直在接受输入并提供行,列和矩阵,但是一旦我进入列表进行计数,就无法给出错误

if matrix[num_rows][num_columns][1] == "x": 
     

IndexError:列表索引超出范围

我的代码段:

def parse_in(input_name):
    list_of_lists = []
    with open(input_name,"r") as f:
        for line in f:
            with open(input_name) as f:
                num_rows, num_columns = [int(x) for x in next(f).split()]

                lines = f.read().splitlines()
            # in alternative, if you need to use the file content as numbers
        matrix = []
        print(lines)
        for x in lines:
            matrix.append(x.split(' '))
        print(matrix)
    return matrix, num_rows, num_columns


def detector(matrix, num_rows, num_columns):
    mine_count = 0
    # For every every space around the square, including itself
    for r in range(num_rows):
        for c in range(num_columns):
            # If the square exist on the matrix
            if 0 <= num_rows + r <= 2 and 0 <= num_columns + c <= 2:
                # If the square contains a mine
                if matrix[r][c] == "*":
                    # Raise the mine count
                    mine_count = mine_count + 1
            # If the original square contains a mine
            if matrix[r][c] == "*":
                print(mine_count)
                # Lower the mine count by 1, because the square itself having a mine shouldn't be counted
                mine_count = mine_count - 1
                print(mine_count)
            return mine_count


def parse_out(output_name, my_solution):
    pass


def my_main(input_name, output_name):
    # 1. We do the parseIn from the input file
    lines, num_rows, num_columns = parse_in(input_name)

    # 2. We do the strategy to solve the problem
    my_solution = detector(lines, num_rows, num_columns)

    # 3. We do the parse out to the output file
    parse_out(output_name, my_solution)


if __name__ == '__main__':
    # 1. Name of input and output files
    input_name = "input_2.txt"
    output_name = "output.txt"

    # 2. Main function
    my_main(input_name, output_name)

2 个答案:

答案 0 :(得分:0)

创建矩阵时,不需要两个循环。您可以直接在读取文件的循环中构建矩阵。您也不需要多次打开文件。

def parse_in(input_name):
    matrix = []
    with open(input_name,"r") as f:
        num_rows, num_columns = [int(x) for x in next(f).split()]
        for line in f:
            matrix.append(line.split(' '))
    return matrix, num_rows, num_columns

您不需要将num_rowsnum_columns传递给detector()函数。与C之类的语言不同,Python知道列表的长度,因此您可以直接循环遍历列表元素。您可以在循环时使用enumerate()来获取索引。

在计算一个正方形旁边的地雷数时,您只需要从r-1r+1以及从c-1c+1循环。并且需要在此循环之前将mine_count设置为0

def detector(matrix):
    result = []
    for r, row in enumerate(matrix):
        result_row = []
        for c, cell in enumerate(row):
            if cell == "*":
                result_row.append(cell)
            else:
                mine_count = 0
                for x in range(c-1, c+2):
                    for y in range(r-1, r+2):
                        if 0 <= x < len(row) and 0 <= y < len(matrix) and matrix[x][y] == "*":
                            mine_count += 1
                result_row.append(str(mine_count))
        result.append(result_row)
    return result

答案 1 :(得分:0)

首先读取文本文件,然后将行内容放入numpy数组中:

with open('test1.txt', 'r') as f:
    all_lines = f.readlines()
    mat_shape = tuple(map(int, all_lines[0].split()))
    lines = [i.strip().split() for i in all_lines[1:]]
lines = np.array(lines)

读取文本文件的第一行,进行拆分,将它们映射为int并将其保存在一个元组中,以便稍后使用它调整矩阵大小。

lines像这样:

[['*' 'o' 'o' 'o' 'o' '*']
 ['o' 'o' '*' 'o' 'o' 'o']
 ['o' 'o' '*' 'o' 'o' '*']
 ['o' 'o' '*' 'o' 'o' 'o']
 ['o' 'o' 'o' 'o' '*' 'o']
 ['o' 'o' 'o' 'o' 'o' 'o']]

使用此函数获取矩阵每个单元的相邻项:

def get_neighbours(lines, cell):
    row, col = cell
    row_max = len(lines)
    col_max = len(lines[0])
    cell_cont = lines[row][col]
    if cell_cont!="*":
        return [lines[row_d + row][col_d + col] for col_d in [-1,0,1] if (0 <= (col_d + col) < col_max) or (col_d == 0 and row_d==0) for row_d in [-1,0,1] if 0 <= (row_d + row) < row_max ].count('*')
    else:
        return '*'

该函数采用整个矩阵和一个特定的单元格,该单元格是行号和列号的元组。如果单元格中有星星,则仅返回'*',否则返回整数-相邻相邻单元格中的星星数。

现在创建一个新数组,并为矩阵的每个单元格调用此函数:

new = []
for i,_ in enumerate(lines):
    for j,_ in enumerate(lines[i]):
        new.append(get_neighbours(lines, (i,j)))
new = np.array(new)

如果您现在通过以下方式将此矩阵重塑为所需格式:

new = new.reshape(mat_shape)

它变成了:

[['*' '2' '1' '1' '1' '*']
 ['1' '3' '*' '2' '2' '2']
 ['0' '3' '*' '3' '1' '*']
 ['0' '2' '*' '3' '2' '2']
 ['0' '1' '1' '2' '*' '1']
 ['0' '0' '0' '1' '1' '1']]

您可以使用以下命令将其写入新的文本文件中:

with open('new1.txt', 'w') as f:
    f.write(all_lines[0])
    for i in new:
        f.write(' '.join(i))
        f.write('\n')

它将以下内容写入new1.txt文件:

6 6
* 2 1 1 1 *
1 3 * 2 2 2
0 3 * 3 1 *
0 2 * 2 2 2
0 1 1 2 * 1
0 0 0 1 1 1