簡體   English   中英

創建數組后,如何正確遍歷CSV文件中的行數組?

[英]How to properly iterate through an array of rows from a CSV file, after the array has been created?

非常抱歉,如果以前已經回答過,但是我搜索了StackOverflow,卻找不到解決該問題的明確解決方案。

我有一個名為“ 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

我的問題:到底為什么會發生?糾正此問題的最佳方法是什么?

您遇到的錯誤意味着變量名稱比實際值更多。

例:

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

更新:

因為是枚舉,“項目”不是一成不變的嗎? 如果以后要更改其數據該怎么辦(例如替換文本字符串)

迭代不會使任何事物變得可變。 一個對象是可變的(並且在for循環主體中對其for突變與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循環外for檢查:

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

如您所見, str.replace()返回一個新字符串,並保留原始字符串不變(當然,字符串是不可變的)。 如果要使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']
>>> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM