【问题标题】:How to search CSV file with multiple search criteria and print row?如何使用多个搜索条件搜索 CSV 文件并打印行?
【发布时间】:2018-09-25 14:28:14
【问题描述】:

我有一个大约 1000 行的 .csv 文件,如下所示:

id,first_name,last_name,email,gender,ip_address,birthday
1,Ced,Begwell,cbegwell0@google.ca,Male,134.107.135.233,17/10/1978
2,Nataline,Cheatle,ncheatle1@msn.com,Female,189.106.181.194,26/06/1989
3,Laverna,Hamlen,lhamlen2@dot.gov,Female,52.165.62.174,24/04/1990
4,Gawen,Gillfillan,ggillfillan3@hp.com,Male,83.249.190.232,31/10/1984
5,Syd,Gilfether,sgilfether4@china.com.cn,Male,180.153.199.106,11/07/1995

到目前为止,我所拥有的代码将要求输入,然后遍历每一行并打印包含输入的行。看起来像这样:

import csv

# Asks for search criteria from user

search = input("Enter search criteria:\n")

# Opens csv data file

file = csv.reader(open("MOCK_DATA.csv"))

# Go over each row and print it if it contains user input.

for row in file:
    if search in row:
        print(row)

我想要的最终结果以及我坚持的目标是能够输入多个由“,”分隔的搜索条件,它将搜索并打印这些行。有点像过滤列表的方法。

例如,如果文件中有多个“David”是“Male”。我可以进入:大卫,男

然后它会打印所有匹配的行,但忽略那些带有“David”即“女性”的行。

【问题讨论】:

  • 我知道这是一个 python 问题,但是grep David file.csv | grep Male?

标签: python python-3.x csv


【解决方案1】:

您可以用逗号分割输入,然后使用all() 和列表推导检查以确保输入中的每个字段都出现在给定的行上。

此示例使用输入的简单拆分,并且不关心每个输入匹配的哪个字段。如果您只想匹配特定列,请考虑使用 csv.DictReader 而不是 csv.reader

import csv
# Asks for search criteria from user
search_parts = input("Enter search criteria:\n").split(",")
# Opens csv data file
file = csv.reader(open("MOCK_DATA.csv"))
# Go over each row and print it if it contains user input.
for row in file:
    if all([x in row for x in search_parts]):
        print(row)

【讨论】:

  • 这是最接近我正在寻找的东西。谢谢!!!您是否有机会知道如何对其进行编码,以便我只需输入字符串的一部分即可找到该行?例如,不是搜索整个“14/05/1995”来显示匹配的行,而是只输入“1995”,它会显示所有具有 1995 的行?
【解决方案2】:

如果您乐于使用第 3 方库,可以使用 pandas

我稍微修改了您的数据以演示一个简单的查询。

import pandas as pd
from io import StringIO

mystr = StringIO("""id,first_name,last_name,email,gender,ip_address,birthday
1,Ced,Begwell,cbegwell0@google.ca,Male,134.107.135.233,17/10/1978
2,Nataline,Cheatle,ncheatle1@msn.com,Female,189.106.181.194,26/06/1989
3,Laverna,Hamlen,lhamlen2@dot.gov,Female,52.165.62.174,24/04/1990
4,David,Gillfillan,ggillfillan3@hp.com,Male,83.249.190.232,31/10/1984
5,David,Gilfether,sgilfether4@china.com.cn,Male,180.153.199.106,11/07/1995""")

# replace mystr with 'file.csv'
df = pd.read_csv(mystr)

# retrieve user inputs
first_name = input('Input a first name\n:')
gender = input('Input a gender, Male or Female\n:')

# calculate Boolean mask
mask = (df['first_name'] == first_name) & (df['gender'] == gender)

# apply mask to result
res = df[mask]

print(res)

#    id first_name   last_name                     email gender  \
# 3   4      David  Gillfillan       ggillfillan3@hp.com   Male   
# 4   5      David   Gilfether  sgilfether4@china.com.cn   Male   

#         ip_address    birthday  
# 3   83.249.190.232  31/10/1984  
# 4  180.153.199.106  11/07/1995  

【讨论】:

  • 感谢您的快速回答。我对熊猫不太熟悉,但如果这是唯一的方法,我会试一试。我正在寻找一种让它工作的方法,以便它要求用户输入,以便每次程序运行时搜索条件可以从一个或多个关键字变化。如果你能给我一个关于如何做到这一点的例子......那就太棒了。 :)
【解决方案3】:

虽然您可以只检查字符串 "David""Male" 是否存在于一行中,但如果您需要检查列值,这将不是很精确。相反,通过csv 读取数据并创建一个存储搜索值和标题名称的namedtuple 对象列表:

from collections import namedtuple
import csv
data = list(csv.reader(open('filename.csv')))
search = namedtuple('search', 'value,header')
searches = [search(i, data[0].index(b)) for i, b in zip(input().split(', '), ['first_name', 'gender'])]
final_results = [i for i in data if all(c.value == i[c.header] for c in searches)]

【讨论】:

    猜你喜欢
    • 2011-10-11
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    • 2020-06-01
    • 2011-04-17
    • 2016-10-20
    相关资源
    最近更新 更多