【问题标题】:How to read several rows from a csv如何从csv中读取几行
【发布时间】:2016-04-03 21:40:45
【问题描述】:

我有一个 csv 文件,其中包含姓名和电话号码等内容。只有在我知道电话号码的情况下,我才对姓名感兴趣。

with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    names =  [record['Name'] for record in reader if record['phone']]

但我也想要相应的电话号码,我试过这个:

user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data['Name'] =  [record['Name'] for record in reader if record['phone']]
    user_data['phone'] = [record['phone'] for record in reader if record['phone']]

但是对于第二个项目,我得到了一个空字符串,我猜record 是一个生成器,这就是为什么我可以对其进行两次迭代。

我尝试过使用元组,但只能这样工作:

user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data['Name'] =  [(record['Name'],record['phone']) for record in reader if record['phone']]

在这种情况下,我将两个变量 phoneName 存储在 user_data['Name'] 中,这不是我想要的。

如果我试试这个:

user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data['Name'],user_data['phone'] =  [(record['Name'],record['phone']) for record in reader if record['phone']]

我收到以下错误:

ValueError: too many values to unpack

编辑:

这是表格的示例:

+--------+---------------+
|电话 |号码 |
+--------+---------------+
|路易斯 | 000 111 22222 |
+--------+---------------+
|保罗 | 000 222 3333 |
+--------+---------------+
|安德里亚 | |
+--------+---------------+
|豪尔赫 | 111 222 3333 |
+--------+---------------+

所以所有行都有名称,但并非所有行都有电话。

【问题讨论】:

  • 尝试zip(*) 转置最后一行的列表。
  • 你能澄清一下你的数据是一列还是多列,如果多列是电话号码和姓名在同一行吗?
  • 我想你是说电话和名字在同一行
  • @PyNEwbie 这是多列,所有行都有名称,但并非所有行都有电话号码,这就是我使用 if record['phone']

标签: python csv list-comprehension


【解决方案1】:

您可以使用dict 将您的元组列表转换为字典。如果您有没有phone 值的记录,您还需要使用get

import csv

user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data = dict([(record['Name'], record['phone']) for record in reader if record.get('phone').strip())

如果您想要分别列出names 和phones,您可以使用* 表达式

with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    names, phones = zip(*[(record['name'], record['value']) for record in reader if record.get('phone').strip()])

【讨论】:

  • 谢谢,两者都有效。 dict 方法是否适用于两个以上的项目?也是把第一个值作为key,这意味着如果有重复的值就会破坏?
  • @是的,它适用于两个以上的项目。如果您的文件中有重复的name,它不会中断,但只会保留最后一个值。如果您有重复的密钥,最好的办法是name 将您的结果保留为tuple 的列表。顺便说一句,这就是 tuple 的用途。如果有帮助,也不要忘记接受答案。
【解决方案2】:

我认为有一个更简单的方法因为它是一个 csv 文件,因为您指出有列标题,然后每一行中都有一个 phone 值,它要么什么都没有,要么什么都没有 - 所以这个测试什么都没有,如果并非没有将姓名和电话添加到 user_data

import csv
user_data = []
with open(f,'rb') as fh:
   my_reader = csv.DictReader(fh)
   for row in my_reader:
       if row['phone'] != ''
           user_details = dict()
           user_details['Name'] = row['Name']
           user_details['phone'] = row['phone']
           user_data.append(user_details)

通过使用 DictReader,我们让魔法发生,所以我们不必担心寻找等。

如果我不明白,而你想要一本字典,那就很简单了

import csv
user_data = dict()
with open(f,'rb') as fh:
   my_reader = csv.DictReader(fh)
   for row in my_reader:
       if row['phone'] != ''
           user_data['Name'] = row['phone']

【讨论】:

  • OP 想要一本字典作为最终结果,你的构造会给他一个字典列表
  • 谢谢,我仍然不清楚,但两个选项都可以工作
  • @PyNEwbie 我已经尝试了您的第二个代码,我有一个分配给名称的电话号码,但如果电话存在,我想要名称和电话。另外由于某种原因,我只得到一行的值,文件有几行。
  • @Luis 获得一行的值可能是因为 python dicts 不支持重复键 - 最后一个获胜。如果您需要重复的密钥,可能的解决方法在这里:stackoverflow.com/questions/10664856/…
【解决方案3】:

你的猜测是对的。如果这是您想要采用的方法 - 迭代两次,您应该使用 seek(0)

reader = csv.DictReader(f)
user_data['Name'] =  [record['Name'] for record in reader if record['phone']]
f.seek(0)   # role back to begin of file ...
reader = csv.DictReader(f)
user_data['phone'] = [record['phone'] for record in reader if record['phone']]

但是,这不是很有效,您应该尝试一次性获取数据。以下内容应一次性完成:

user_data = {}

def extract_user(user_data, record):
    if record['phone']:
        name = record.pop('name')
        user_data.update({name: record})

[extract_user(user_data, record) for record in reader]

例子:

In [20]: cat phones.csv
name,phone
hans,01768209213
grettel,
henzel,123457123

In [21]: f = open('phones.csv')

In [22]: reader = csv.DictReader(f)

In [24]: %paste
user_data = {}

def extract_user(user_data, record):
    if record['phone']:
        name = record.pop('name')
        user_data.update({name: record})

[extract_user(user_data, record) for record in reader]

## -- End pasted text --
Out[24]: [None, None, None]

In [25]: user_data
Out[25]: {'hans': {'phone': '01768209213'}, 'henzel': {'phone': '123457123'}}

【讨论】:

  • 我不确定这是不是问题 - 最后一个块重新打开了文件。问题在于拆包。
【解决方案4】:

您要查找的内容是否有可能丢弃了数据文件中的一些信息?

In [26]: !cat data00.csv
Name,Phone,Address
goofey,,ade
mickey,1212,heaven
tip,3231,earth

In [27]: f = open('data00.csv')

In [28]: r = csv.DictReader(f)

In [29]: lod = [{'Name':rec['Name'], 'Phone':rec['Phone']} for rec in r if rec['Phone']]

In [30]: lod
Out[30]: [{'Name': 'mickey', 'Phone': '1212'}, {'Name': 'tip', 'Phone': '3231'}]

In [31]: 

另一方面,如果您的文件仅包含 NamePhone 列,则 只是

In [31]: lod = [rec for rec in r if rec['Phone']]

【讨论】:

    【解决方案5】:

    我通常使用行索引:

    input = open('mycsv.csv', 'r')
    user_data = {}
    
    for row in csv.reader(input):
        if row[<row # containing phone>]:
            name = row[<row # containing name>]
            user_data[name] = row[<row # containing phone>]
    

    【讨论】:

      【解决方案6】:

      你一直都是对的,除了拆包。

      result = [(record["name"], record["phone"]) for record in reader if record["phone"]]
      # this gives [(name1, phone1), (name2,phone2),....]
      

      你必须做[dostuff for name, phone in result] 而不是name,phone = result,这在语义和句法上都没有意义。

      【讨论】:

        猜你喜欢
        • 2015-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-14
        • 2019-05-27
        相关资源
        最近更新 更多