python - Python CSV Reader 搜索字符串找到匹配项
问题描述
再次回到另一个问题。
前言:用 Qt Designer 构建一个 GUI,一个搜索按钮,解析 csv 数据,并用找到的数据构建我的 TableWidget。
我有一个文件,其中包含两个相似的结果,例如,一个位置标记为 Reddit(北)和 Reddit(南)。如果我搜索 Reddit,只显示第一个结果,但是当我再次按下搜索按钮时,它只显示第一个结果,而不是第二个。
问题:如何在第一次匹配时停止 csv 阅读器,用它从第一次匹配中找到的数据填写表格,然后再次点击搜索按钮以清除第一次匹配并显示第二次匹配?
def search(self):
self.table_search.setRowCount(6)
self.table_search.setColumnCount(1)
self.table_search.verticalHeader().setDefaultSectionSize(20)
self.table_search.verticalHeader().setVisible(True)
self.table_search.setVerticalHeaderLabels([
'Location ID:',
'Location Name:',
'Cost Center:',
'Street Address:',
'City:',
'State:']
)
# taking input from a PyQt line edit box
search = self.lineedit_locsearch.text()
search_string = search.strip().upper() # stripping white space from the string
# containers for specific data from the csv file
locid = ''
locname = ''
loccost = ''
locaddress = ''
loccity = ''
locstate = ''
with open('data/loc.csv', "r") as locdata:
reader = csv.reader(locdata)
for row in reader:
for field in row:
if field == search_string:
locid = row[0]
locname = row[1]
loccost = row[2]
locaddress = row[3]
loccity = row[4]
locstate = row[5]
locdata.close()
self.table_locsearch.setItem(0, 0, QtWidgets.QTableWidgetItem(locid))
self.table_locsearch.setItem(1, 0, QtWidgets.QTableWidgetItem(locname))
self.table_locsearch.setItem(2, 0, QtWidgets.QTableWidgetItem(loccost))
self.table_locsearch.setItem(3, 0, QtWidgets.QTableWidgetItem(locaddress))
self.table_locsearch.setItem(4, 0, QtWidgets.QTableWidgetItem(loccity))
self.table_locsearch.setItem(5, 0, QtWidgets.QTableWidgetItem(locstate))
解决方案
您可以将您的 CSV 阅读/搜索外部化并使其成为生成器,以便它记住它停止的位置,即:
@staticmethod
def search_csv(path, search):
with open(path, "r") as f:
for row in csv.reader(f):
if search in row:
yield row
您现在可以将其用作搜索迭代器来查看搜索结果。实际利用率可能取决于您如何实现系统的其余部分 - 最好只保留对当前搜索迭代器的引用(如果可用)(并且搜索字符串没有更改),或者创建一个新的 if不是。例如,对您的search()
方法进行就地更改以启用它:
def search(self):
# you could externalize the table setup as it's always static
self.table_search.setRowCount(6)
self.table_search.setColumnCount(1)
self.table_search.verticalHeader().setDefaultSectionSize(20)
self.table_search.verticalHeader().setVisible(True)
self.table_search.setVerticalHeaderLabels([
'Location ID:',
'Location Name:',
'Cost Center:',
'Street Address:',
'City:',
'State:'])
search = self.lineedit_locsearch.text().strip().upper() # get the current search string
search_gen = getattr(self, "_search_gen", None) # attempt to grab the current search
if search_gen is None or search_gen["search"] != search: # we need a new search
search_gen = {"generator": self.search_csv("data/loc.csv", search),
"search": search} # store the search string as well
setattr(self, "_search_gen", search_gen) # save it to the object
try:
result = next(search_gen["generator"])
except StopIteration: # no (more) results
result = [] # alternatively you may show that there are no (more) results
# to ensure validity, let's force the `result` to have at least 6 fields:
result += [""] * (6 - len(result)) # fill the non-populated fields with empty strings
for row in range(6): # fill the table iteratively
self.table_locsearch.setItem(row, 0, QtWidgets.QTableWidgetItem(result[row]))
它本质上检查当前实例上是否已经存在_search_gen
字典,以及它是否包含与其中的内容相同的搜索字符串self.lineedit_locsearch
- 如果是,则它使用现有的生成器继续搜索 CSV,如果没有,它会创建一个新的。无论哪种方式,生成器都用于获取(下一个)结果,然后填满表格。作为奖励,我们确保结果至少有 6 个字段,以便即使找到的 CSV 行没有全部 6 个字段,也可以正确填充表格。
我不确定,如果您一直需要重新配置表格 - 也许您可以在创建搜索结果窗口/面板/框架/任何内容时创建它,然后继续调用该search()
方法来更新结果。
最后,当您想关闭搜索时,请确保使用 .使生成器无效delattr(self, "_search_gen")
。另请注意,data/loc.csv
在搜索期间,传递的文件 ( ) 将在读取模式下保持打开状态,直到找不到更多结果或您如上所述使搜索生成器无效。
推荐阅读
- c++ - 如何避免函数中的参数过多。C++
- azure - Azure AD B2C 自定义策略 + Application Insights
- asp.net - 使用 ASP.NET MVC 中的 Content 文件夹作为文件系统来存储 PDF 文件是一种好习惯吗?
- java - 我正在研究 Java 中的静态和实例变量,我无法理解代码的输出
- google-oauth - Google 身份验证端点重定向到 400 错误页面
- java - java Netbeans显示带参数的ireport文档但选择日期时出错,它说报告上没有文档
- php - 使用文件 guzzle laravel 上传数据
- docker - 在 Ubuntu 20.04 LTS(Vmware)上安装 docker 失败
- python - 如何将 Fairlearn 与自定义公平约束一起使用?
- javascript - 如何在本机反应中仅更改特定的子样式属性?