经过多次尝试后,我能够获取下面的代码,为给定的特定csv文件索引特定的列和行。现在我想将下面的代码转换成字典,我阅读了关于dict和zip的文档,但是我还不清楚......
CSV文件包含500条记录和列A:L,对应于以下标题:
first_name,last_name,company,address,city,county,state,zip,phone1,phone2,email,web
import csv
f= open('us-500.csv', 'rU')
reader = csv.reader(f) # use list or next
rows = list(reader)
for row in rows[0:20]:
print "".join(row[8])
答案 0 :(得分:1)
我会猜测你想要的东西。
您有一个CSV文件,例如10列。
您希望使用每行第8列作为键的字典,以及整行(即所有列的列表)作为相应的值。*
因此,您只需要提供行列表的list(reader)
,而不是d = {row[8]: row for row in reader}
:
d = dict((row[8], row) for row in reader)
或者,如果您使用的是Python 2.5并且没有字典理解:
John, Smith, 2, 3, 4, 5, 6, 7, 8, 9, 10
Ed, Jones, 20, 30, 40, 50, 60, 70, 80, 90, 100
所以,给定这个输入文件:
{'8': ['John', 'Smith', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
'80': ['Ed', 'Jones', '20', '30', 40', '50', '60', '70', '80', '90', '100']}
你会得到这本词典:
{{1}}
*这假设第8列值是唯一的。否则,这根本没有意义。您可能会想要一个多字典,将每个第8列值映射到具有该第8列值的所有行的列表,或者将每个第8列值映射到拉链的“多行”字典。将每个具有该列-8值的行的每个列值或者......谁知道什么。一旦你理解了基本想法并知道你想要哪一个,所有这些都很容易编写。
答案 1 :(得分:0)
如果您可以将数据分成两个列表(按照您希望的顺序排列),那么您就可以转换为dictionarys了。
>>> list_1 = ['pie','farts','boo']
>>>
>>> list_2 = ['apple','stanky','scary']
>>>
>>> dict(zip(list_1,list_2))
{'boo': 'scary', 'farts': 'stanky', 'pie': 'apple'}
>>>
>>> dict(zip(list_2,list_1))
{'apple': 'pie', 'stanky': 'farts', 'scary': 'boo'}
>>>
zip命令有点酷,因为它将两个列表转换为一个列表,其中包含较小的列表,
>>> list(zip(list_1,list_2))
[('pie', 'apple'), ('farts', 'stanky'), ('boo', 'scary')]
然后你只需将其转换成字典
>>> dict(zip(list_1,list_2))
{'boo': 'scary', 'farts': 'stanky', 'pie': 'apple'}
答案 2 :(得分:0)
您可以使用dict
理解。
list1 = range(10)
list2 = range(20)
a = {k: v for k, v in zip(list1, list2)}
print a
甚至可以使用dict()
方法。
b = dict(zip(list1, list2))
两种情况下的输出是: -
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
答案 3 :(得分:0)
根据你的评论,听起来你要求的是这样的:
“multi-dict”只是一个dict映射键到某种集合,如集合或列表。您可以使用defaultdict
非常轻松地构建一个。
您可以使用enumerate
函数获取每个行号及其值列表。
所以,让我们为你的数据构建几个索引:
import collections
import csv
f= open('us-500.csv', 'rU')
reader = csv.reader(f) # use list or next
rows = list(reader)
phone1_index = collections.defaultdict(set)
phone2_index = collections.defaultdict(set)
for i, row in enumerate(rows):
phone1_index[row[8]].add(i)
phone2_index[row[9]].add(i)
(请注意,这与典型数据库中的索引并不完全相同 - 它与查找所有行where phone1 == ?
一样好,但对where phone1 < ?
没有帮助。)
但实际上,没有理由在指数方面进行思考。如果你只是将行本身存储在dicts中,那么你就不会浪费任何空间;您可以在Python中对同一个对象进行两次引用,而无需复制所有数据。
存在一个小技术问题,因为行是列表,因此是可变的,因此不能存储在集合中。但是你可能实际上并不希望它们是可变的,它们恰好就是这样,所以你可以改为使用元组:
f= open('us-500.csv', 'rU')
reader = csv.reader(f) # use list or next
phone1_map = collections.defaultdict(set)
phone2_map = collections.defaultdict(set)
for row in reader:
row = tuple(row)
phone1_map[row[8]].add(row)
phone2_map[row[9]].add(row)
虽然我们对此感到满意,但对于namedtuple
来说这似乎很不错:
header = 'first_name, last_name, company, address, city, county, state, zip, phone1, phone2, email, web'
Row = collections.namedtuple('Row', header.split(', '))
f= open('us-500.csv', 'rU')
reader = csv.reader(f) # use list or next
phone1_map = collections.defaultdict(set)
phone2_map = collections.defaultdict(set)
for row in reader:
row = Row(row)
phone1_map[row.phone1].add(row)
phone2_map[row.phone2].add(row)
所以,现在,如果您想查找phone1
或phone2
为1.555.555.1212
的所有人的姓氏:
matches = phone1_map['1.555.555.1212'] | phone2_map['1.555.555.1212']
names = {match.name for match in matches}
答案 4 :(得分:0)
编辑 - &gt;根据提问者的评论,我认为这更符合要求(使用DictReader使这更简单):
import csv
with open('c:\us-500.csv', 'rU') as f:
reader = csv.DictReader(f)
address_book = {}
for row in reader:
address_book[row['phone1']] = row
为该文件提供一个字典,主键为第8列&#34; phone1&#34;。访问这样的值。
address_book['555-1212']['first_name']
address_book['978-3425']['email']
Edit2 - &gt;现在删除原始答案。基本上它是重新实现DictReader功能。