使用zip或dict函数将列表转换为Python中的字典

时间:2014-10-16 19:19:30

标签: python dictionary

经过多次尝试后,我能够获取下面的代码,为给定的特定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])

5 个答案:

答案 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)

所以,现在,如果您想查找phone1phone21.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功能。