2017-10-18 57 views
1

非常抱歉,如果这之前回答,但我搜索StackOverflow并找不到解决问题的明确解决方案。如何在数组创建后正确迭代CSV文件中的行数组?

我有称为“myFile.csv”的CSV文件

  • 的文件是逗号(“”)分隔
  • 第一行包含列标题,而随后的所有行都是数据行。

我打开和读取CSV文件,指定每行称为“myArray的”数组,旨在供以后使用,为不同的事情...

with open("..\dirX\myFile.csv", 'rb') as fileHandle: 
    myArray = [] 
    for row in csv.reader(fileHandle, delimiter=','): 
     myArray.append(row) 

我可以成功打印从各行阵列...

print myArray[0] # Works fine! Prints header row. 
print myArray[1] # Works fine! Prints first data row. 

但是,当我试图循环通过从CSV文件创建的数组,以提取每一行,我得到一个失败。 for循环代码如下...

for idx, row in myArray: # <--- This where the error message points to 
    print 'Index = ' + str(idx) 
    print row 

该错误消息我得到的是:

Traceback (most recent call last): 
    File “myScript.py”, line 155, in (module) 
     For idx, row in myArray: 
ValueError: too many values to unpack 

我的问题:究竟为什么会发生这种情况,什么是纠正这一点的最好办法问题?

回答

1

列表的行为与任何其他序列的不同行为不同:您只获取项目,而不是索引(就像迭代csv.reader时你只有行,而不是索引)。

如果你想拥有这两个指数和物品,你可以使用enumerate()

for index, item in enumerate(somelist): 
    print("item at {} is {}".format(index, item)) 

更新:

因为它列举了,是不是 “项” 不可改变的?如果我稍后想要更改它的数据(例如,替换文本字符串),该怎么办?

迭代不会使任何更多或更少变化。一个对象是可变的(并且在for循环体中突变它的作用与循环外相同),或者它不是,句点。

看来你对变异和重新定义的区别感到困惑。下面是与可变对象列表的例子:

>>> data = [dict(a=i) for i in xrange(3)] 
>>> data 
[{'a': 0}, {'a': 1}, {'a': 2}] 
>>> for item in data: 
...  item["b"] = item["a"] + 42 
... 
>>> data 
[{'a': 0, 'b': 42}, {'a': 1, 'b': 43}, {'a': 2, 'b': 44}] 

正如你所看到的项目是完全可变的..

现在你不能不可变对象的列表做到这一点,不是因为for循环(您使用enunerate或不使用在这里无关紧要),但是因为不可变对象是不可变的。让我们首先检查这个for循环外:

>>> s = "foo 1" 
>>> s.replace("1", "2") 
'foo 2' 
>>> s 
'foo 1' 

正如你所看到的,str.replace()返回一个新字符串并保持原来不变(当然 - 字符串是不可变的)。如果你想s成为“富2”,你必须重新绑定s,使其指向另一个字符串:

>>> s 
'foo 1' 
>>> id(s) 
139792880514032 
>>> s = s.replace("1", "2") 
>>> s 
'foo 2' 
>>> id(s) 
139792880474080 

注意,重新绑定一个变量不影响指向同一对象的其他变量:

>>> s1 = "aaa" 
>>> id(s1) 
139792880524584 
>>> s2 = "bbb" 
>>> id(s2) 
139792880522104 
>>> s1 = "aaa" 
>>> s1 
'aaa' 
>>> id(s1) 
139792880524584 
>>> s2 = s1 
>>> s2 
'aaa' 
>>> id(s2) 
139792880524584 
>>> s2 is s1 
True 
>>> # now let's rebind s1:  
>>> s1 = "bbb" 
>>> s1 
'bbb' 
>>> id(s1) 
139792880522104 
>>> s2 
'aaa' 
>>> id(s2) 
139792880524584 
>>> s2 is s1 
False 
>>> 

所以重新绑定迭代变量(item在我们上面的片断)技术的工作原理(此变量的反弹),但是这不会影响到列表或任何你在上面迭代(就像rebindi NG s1不会影响s2):如果你有一个字符串列表,并希望更新的地方列表

>>> data = ["aaa", "bbb", "ccc"] 
>>> for item in data: 
...  print "item before : {}".format(item) 
...  item = 42 
...  print "item after : {}".format(item) 
...  print "data : {}".format(data) 
... 
item before : aaa 
item after : 42 
data : ['aaa', 'bbb', 'ccc'] 
item before : bbb 
item after : 42 
data : ['aaa', 'bbb', 'ccc'] 
item before : ccc 
item after : 42 
data : ['aaa', 'bbb', 'ccc'] 

所以,你必须变异列表本身 - 这需要有匹配的指标也是如此,这你使用enumerate

>>> data = ["aaa", "bbb", "ccc"] 
>>> for index, item in enumerate(data): 
...  data[index] = item.upper() 
... 
>>> data 
['AAA', 'BBB', 'CCC'] 

注意,这里我们不重新绑定迭代变量,但变异的data列表本身。它的工作原理只是一样没有for循环:

>>> data = ["aaa", "bbb", "ccc"] 
>>> item = data[0] 
>>> item 
'aaa' 
>>> item = "AAA" 
>>> item 
'AAA' 
>>> data 
['aaa', 'bbb', 'ccc'] 

与:

>>> data = ["aaa", "bbb", "ccc"] 
>>> data[0] = "AAA" 
>>> data 
['AAA', 'bbb', 'ccc'] 
>>> 
+0

因为它被枚举,是不是“项”不可变的?如果我想稍后更改它的数据(例如替换文本字符串),该怎么办? –

+0

@InformationTechnology:尝试提供的解决方案,看看它是否使'item'不可变。实验的结果是什么? – wwii

+0

@InformationTechnology比较我的更新答案 –

2

您的错误意味着变量名称比实际值更多。

例如:

lst = [1,2] 
a,b = lst # <-- this is ok 

a,b,c = lst # error 

所以如果你需要IDX,你可以尝试使用枚举,因此每次迭代都会产生的情况下,两个值

for idx, row in enumerate(myArray): 
    print 'Index = ' + str(idx) 
    print row 

要更改元素

res = [] 
for idx, row in enumerate(myArray): 
    print 'Index = ' + str(idx) 
    print row 
    #do change 
    res.append(changed_row) 
+0

不枚举该行使其完全不可改变/不可改变?以后如何能够更改行中的值?例如,如果我想在以后更换行中的字符串,该怎么办? –

+0

@InformationTechnology https://docs.python.org/2/library/functions.html#enumerate here是文档。它不会改变任何东西。 – galaxyan

+0

@InformationTechnology顺便说一句,如果你想在迭代过程中改变元素,你最好创建另一个列表 – galaxyan