创建数组后,如何正确地遍历 CSV 文件中的行数组?
How to properly iterate through an array of rows from a CSV file, after the array has been created?
非常抱歉,如果之前有人回答过这个问题,但我搜索了 Whosebug,但找不到解决问题的明确解决方案。
我有一个名为“myFile.csv”的 CSV 文件
- 文件以逗号(“,”)分隔
- 第一行包含列 header,而所有后续行都是数据行。
我打开并阅读 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
我的问题:究竟为什么会发生这种情况以及解决此问题的最佳方法是什么?
您遇到的错误意味着变量名多于实际值。
示例:
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)
列表的行为与任何其他序列 wrt/ 迭代没有不同:你只得到项目,而不是索引(就像在 csv.reader
上迭代时你只得到行,而不是索引)。
如果你想同时拥有索引和项目,你可以使用enumerate()
:
for index, item in enumerate(somelist):
print("item at {} is {}".format(index, item))
更新:
Because it's enumerated, isn't "item" immutable? What if I want to change it's data, later (e.g. replace text strings)
迭代不会使任何东西或多或少变得可变。一个对象要么是可变的(并且在 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()
returns 一个新字符串并保持原始字符串不变(当然 - 字符串是不可变的)。如果你想让s
变成"foo 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
在我们上面的片段中)在技术上是可行的(这个变量是反弹)但这不会影响列表或你在上面迭代的任何东西(就像重新绑定 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']
>>>
非常抱歉,如果之前有人回答过这个问题,但我搜索了 Whosebug,但找不到解决问题的明确解决方案。
我有一个名为“myFile.csv”的 CSV 文件
- 文件以逗号(“,”)分隔
- 第一行包含列 header,而所有后续行都是数据行。
我打开并阅读 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
我的问题:究竟为什么会发生这种情况以及解决此问题的最佳方法是什么?
您遇到的错误意味着变量名多于实际值。
示例:
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)
列表的行为与任何其他序列 wrt/ 迭代没有不同:你只得到项目,而不是索引(就像在 csv.reader
上迭代时你只得到行,而不是索引)。
如果你想同时拥有索引和项目,你可以使用enumerate()
:
for index, item in enumerate(somelist):
print("item at {} is {}".format(index, item))
更新:
Because it's enumerated, isn't "item" immutable? What if I want to change it's data, later (e.g. replace text strings)
迭代不会使任何东西或多或少变得可变。一个对象要么是可变的(并且在 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()
returns 一个新字符串并保持原始字符串不变(当然 - 字符串是不可变的)。如果你想让s
变成"foo 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
在我们上面的片段中)在技术上是可行的(这个变量是反弹)但这不会影响列表或你在上面迭代的任何东西(就像重新绑定 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']
>>>