Python字典,整数计数保存
我正在尝试统计一组整数的数量。我有一个csv文件,里面有一串数字,比如4, 245, 34, 99, 340,等等。我想做的是返回一个字典,这个字典的每一对键值对中,键是csv文件中的一个整数,而值是这个整数在列表中出现的次数。我不太确定我哪里做错了,希望能得到一些帮助。
allCounts = dict()
rows = csv.reader(open('...csv'), delimiter=',')
for intValue in rows:
intVal = intValue[0]
for intVal, numAppearances in allCounts:
if intVal in allCounts:
allCounts[numAppearances] = allCounts[numAppearances]+1
else:
allCounts[numAppearances] = 1
3 个回答
去掉 intVal = intValue[0]
这一行。
因为 intValue 是一个字符串,所以你得到的只是这个字符串的第一个字符。你真正想要的是 intValue = int(intValue)
,这样才能把字符串转换成数字。
另外,你的逻辑有点问题——现在 allCounts 被初始化为空字典,这样是无法进行遍历的。你应该遍历 csv.reader
返回的值,而你已经在做这个了。你的逻辑差不多了,但可惜这不是马蹄铁或手榴弹,不能只差一点就算对。你想要的是这个:
# Checks to see if intValue is a key in the dictionary
if intValue in allCounts:
# If it is then we want to increment the current value
# += 1 is the idiomatic way to do this
allCounts[intValue] += 1
else:
# If it is not a key, then make it a key with a value of 1
allCounts[intValue] = 1
你现在做的事情是对每一个单元格都遍历整个字典,这样做有点奇怪,可能不是你想要的效果。其实你只需要在字典里查找一下,然后把对应的键加一就可以了。所以:
# first part stays mostly the same
rows = csv.reader(open("...csv") )
allCounts = {}
for row in rows:
for field in row:
allCounts[field] = allCounts.get(field, 0) + 1
最后一行使用了字典的一个很不错的功能,就是如果找不到某个键,它会返回一个默认值。
在你的代码里,有一些值得注意的问题。最主要的问题出现在第四和第五行。你从选中的行中提取了第一个字段,并把它赋值给了 intVal
,但接下来你又用这个值作为键去遍历字典,这样就完全覆盖了 intVal
的值。这意味着你之前的赋值根本没有起作用。
你的 if
条件是没希望的。你在检查某个键是否在字典里,但你得到这个键的方式是从同一个字典里遍历键。那当然这个键是存在于字典里的。
下一个问题是你的 else
条件在修改一个你正在遍历的集合。Python 对于字典的这种操作没有保证,所以最好不要这样做。
其实根本没有必要遍历整个字典。你可以直接获取你感兴趣的键值对。你应该遍历的是文件中的整数列表。
CSV 文件的结构总是由一系列值(通常用逗号分隔)组成,这些值形成了行,而行之间用换行符分隔。CSV 模块保持了这种结构,返回的是一个列表的列表。要获取实际的值,你需要遍历每一行,然后再遍历该行中的每一个字段。你的代码是遍历每一行,然后对每一行的字典中的每一个键进行遍历,却忽略了字段。
听起来你想要的是一个计数器对象:
http://docs.python.org/library/collections.html#counter-objects
另外,我觉得你可能还想用CSV模块:
http://docs.python.org/library/csv.html
使用这些内置模块应该会让事情变得简单很多 :)
要获取行数据,像这样应该可以工作:
csvfile = open("example.csv")
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, dialect)
然后你应该能够做到这一点:
c = Counter(reader)