【问题标题】:Use row and col to find a letter in a txt.file使用 row 和 col 在 txt.file 中查找字母
【发布时间】:2020-11-21 23:06:18
【问题描述】:

我创建了一个包含不同句子的 txt.file,字母的位置之间没有联系,并希望将其保存为 Python 中的字典,然后使用 row 和 col 来确定此文件中的任何特定字母.

在代码中我想让Python问两个问题来确定一个特定的字母:

  1. 询问要查看的文件
  2. 求两个坐标(行号和列号)

这是我目前得到的:

def save_rows(filename):           
    with open(filename, 'r') as f:
        answer = {}
        for line in f:
            line = line.split()
            if not line:  # empty line?
                continue
            answer[line[0]] = line[1:]

        
def main():
    filename = input("Input the file:")
    indexed_file = save_rows(filename)
    row = input("Input row-and column number:")

我该怎么做?

【问题讨论】:

  • 从文件的行中创建dict 是不必要的复杂化,至少对于这个特定问题是这样。您是否需要该结构来处理您将在代码中其他地方执行的其他操作?
  • 嗨,不,我不需要这个结构来处理其他事情,但我确实需要学习如何去做。但是现在我更感兴趣的是如何找到两个坐标上的哪个字母。
  • 您似乎在循环播放行,但并未在指定的行上停止。 Col 看起来不错,但请保留,因为用户可以提供比行中最高的列更大的列。
  • 你在数行数和列数,是像人一样从 1 开始数,还是像蟒蛇一样从 0 开始数?

标签: python


【解决方案1】:

一个简单的方法是这样的:

def get_char_at(filename, row, col):
    row = int(row)
    col = int(col)
    with open(filename) as f:
        lines = f.read().splitlines()
    if row >= len(lines):
        raise KeyError(f"File {filename} doesn't contain {row} lines")
    if col >= len(lines[row]):
        raise KeyError(f"Line {row} doesn't contain {col} characters")
    return lines[row][col]

if __name__ == '__main__':
    filename = input('Input file name: ')
    row = input('Input row: ')
    col = input('Input col: ')
    print(get_char_at(filename, row, col))

f.read().splitlines() 很方便,因为它会自动删除每行末尾的换行符。这里要注意的主要事情是列表(如lines)和字符串(如lines 中的每个项目)都是可索引的。 lines[row] 得到你想要的行,lines[row][col] 得到你该行中的字符。 Python 中的索引从 0 开始,因此编写时,提供 00 将使您获得文件中的第一个字符。如果您愿意,可以根据需要减去一个以从 1 开始。

注意:这是一种简单明了的方法,但不一定是最简单的方法。主要的缺陷是这会将整个文件一次读入内存。这通常适用于大小合理的文本文件。如果您需要处理非常大的文件,遍历其行而不是一次读取它们会更有效。但是,您将无法正确索引到您需要的行。所以get_char_at 可能看起来像:

def get_char_at(filename, row, col):
    row = int(row)
    col = int(col)
    with open(filename) as f:
        for index, line in enumerate(f):
            if index == row:
                if col >= len(line) - 1: # subtract to account for the newline
                    raise KeyError(f"Line {row} doesn't contain {col} characters")
                return line[col]
    raise KeyError(f"File {filename} doesn't contain {row} lines")

你遍历文件的行。 enumerate 提供您当前所在行的索引。如果你得到正确的行,返回字符(假设它有足够的)。另一方面,如果你通过整个文件而没有到达指定的行,它显然没有那么多行。

【讨论】:

  • 谢谢!我试过了,它奏效了!并感谢您解释步骤/代码!
  • @idlatva 很高兴它成功了!请单击复选标记以接受答案。 (您也可以通过点击向上箭头来投票。)
【解决方案2】:

你可以试试linecache:

import linecache

def main():
    filename = input("Input the file: ")
    line_num, col_num = [int(x) for x in input("Input row-and column number: ").split()]
    line = linecache.getline(filename, line_num)
    linecache.clearcache()
    if not line.strip() and col_num > 0 and col_num < len(line):
        print(line[col_num-1])
    else:
        print(f'No letter in line {line_num} and col {col_num}')   
  • linecache.getline() 打开文件并获取所需的行
  • linecache.clearcache() 在这里,以防您修改之前读取的行(例如,通过编辑文件)并想要读取(并缓存)修改后的行
  • not line.strip() 仅跳过包含空格的行(有关详细信息,包括如何检查空行,请参阅 python: how to check if a line is an empty line
  • 假设用户使用1 指定第一列,则需要col_num-1

如果您想在dict 中保存不只有空格的行,您的save_rows() 可以简化为:

def save_rows(filename):
    with open(filename) as f:
        return {i:line for i, line in enumerate(f) if line.strip()}

这样您将有一个dictkeys 行号和values 行。

编辑(基于 cmets 中的询问):要围绕允许的输入实现一些逻辑,您可以尝试:

import sys

while True:
    user_input = input("Input row-and column number: ")
    if user_input == 'exit':
        sys.exit()
    try:
        line_num, col_num = [int(x) for x in user_input.split()]
    except ValueError:
        print('Invalid input. Try again.')
    else:
        break

print(line_num, col_num)

上面的部分一直等到用户输入有效的输入。在这种情况下,这恰好是两个数字。如果用户没有提供有效输入,则会打印一条消息,并再次提示用户提供两个数字。如果用户输入的数字少于或多于两个,则会引发ValueError。如果用户不输入数字,也会发生同样的情况。最后,用户输入exit 程序exits。如果您不想给用户多次输入有效输入的机会(但只有一次),您可以删除 while

【讨论】:

  • 谢谢!如果我希望程序在我在“输入行号和列号”问题上写“退出”时退出,我该怎么做?我试过 if row and col == "exit" 然后返回,但没有用。
  • @idlatva 我更新了答案。我希望这就是你要找的。​​span>
  • 谢谢!这正是我想要的!
猜你喜欢
  • 1970-01-01
  • 2018-12-19
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
相关资源
最近更新 更多