我想了解Delphi中的泛型,但是TList有一個非常基本的問題。如何在使用for-in循環迭代時更新TList?
我已經成功創建了一個列表整數並填充了1000個奇數。我想改變列表中每個可以被3整除的數字。我認爲我可以做這樣的事情。
For I in Mylist Do
Begin
If (I mod 3)= 0 Then
I:=0;
End;
這顯然不起作用,所以我會很感激有人解釋什麼會。
我想了解Delphi中的泛型,但是TList有一個非常基本的問題。如何在使用for-in循環迭代時更新TList?
我已經成功創建了一個列表整數並填充了1000個奇數。我想改變列表中每個可以被3整除的數字。我認爲我可以做這樣的事情。
For I in Mylist Do
Begin
If (I mod 3)= 0 Then
I:=0;
End;
這顯然不起作用,所以我會很感激有人解釋什麼會。
你的代碼不會工作,因爲你試圖修改循環中的循環控制變量(I
),這是不允許的。它告訴你的是,在編譯器錯誤:
[dcc32 Error] Project1.dpr(23): E2081 Assignment to FOR-Loop variable 'i'
如果要修改的列表中,您需要通過列表迭代老式的方式(通過索引)來代替。
for i := 0 to List.Count - 1 do
if (List[i] mod 3) = 0 then
List[i] := 0;
是的,但我會加上:「如果你想修改列表,你需要用老式的方式迭代列表(通過索引)而不是枚舉器(請注意Delphi的集合中沒有迭代器)。「 –
@Rudy有迭代器。他們只是作爲統計員被錯誤地命名。 –
@Rudy:我同意我應該用「修改列表」加以澄清。儘管如此,[文檔](http://docwiki.embarcadero.com/RADStudio/XE6/en/Declarations_and_Statements#Iteration_Over_Containers_Using_For_statements)指的是'forin'作爲迭代而不是枚舉。我在某種程度上改寫了這個句子。 –
uses
System.Generics.Collections;
procedure TForm1.BitBtn1Click(Sender: TObject);
var
_List: TList<integer>;
i: integer;
begin
_List := TList<integer>.Create;
try
// Add few odd numbers
for i := 0 to 100 do
begin
if (i mod 2) <> 0 then
_List.Add(i);
end;
// Replace numbers with 0 that divides by 3
for i := 0 to _List.Count - 1 do
begin
if (_List[i] mod 3) = 0 then
_List[i] := 0;
end;
// Show new list
for i := 0 to _List.Count - 1 do
OutputDebugstring(PWideChar(IntToStr(_List[i])));
finally
FreeAndNil(_List);
end;
end;
你不重複自己改變(如我),你想改變值(例如_List [1])
_List是一個局部變量,不能從其他地方訪問。你爲什麼要FreeAndNil呢? –
它有什麼不對? –
我沒有說這是錯的。我只是問你爲什麼這樣做。該變量處於其範圍的最後,並且無法從其他任何地方訪問,所以我想知道爲什麼使用'FreeAndNil'而不是'.Free'。 –
您使用的是for..in
循環,它採用的是隻讀的枚舉。此代碼:
For I in Mylist Do
Begin
If (I mod 3) = 0 Then
I := 0;
End;
實際上是這樣做的:
Enum := Mylist.GetEnumerator;
while Enum.MoveNext do
Begin
I := Enum.Current;
If (I mod 3) = 0 Then
I := 0;
End;
這就是爲什麼你不能修改在for..in
循環列表內容。你必須使用一個老式的for
循環,而不是使用TList<T>.Items[]
屬性來訪問值:
For I := 0 to Mylist.Count-1 Do
Begin
If (Mylist[I] mod 3) = 0 Then
Mylist[I] := 0;
End;
更新:到然後取出零,你可以這樣做:
For I := Mylist.Count-1 downto 0 Do
Begin
If Mylist[I] = 0 Then
Mylist.Delete(I);
End;
或者,在初始循環中執行以便不需要第二個循環:
For I := Mylist.Count-1 downto 0 Do
Begin
If (Mylist[I] mod 3) = 0 Then
Mylist.Delete(I);
End;
非常感謝 - 這非常有幫助,我已成功修改了我的代碼。但是,這又提出了另一個問題。我將如何去除列表中現在爲零的所有項目? (當然,有效縮短名單)。 – user3861642
你將不得不循環遍歷列表(向後)第二次尋找零。我用例子更新了我的答案。 –
這是Delphi語言非常薄弱的一個領域。其他語言具有強大的迭代器,允許您對集合進行變異。 –
我想知道Embarcadero需要多少工作才能讓枚舉器的'Current'屬性被讀/寫而不是隻讀。 –
可能的重複項http://stackoverflow.com/q/1105519/960757,http://stackoverflow.com/q/2246087/960757。 – TLama