2015-12-26 34 views
1

我有一個進程將數據讀入150多個臨時數組,處理數據並從臨時數組複製到工作數組中。工作陣列在一個全局數組中,因此我可以導入多個數據,這意味着我可以重複同一個過程多達100次,最後使用大數組中的一組數據來保存我可以使用,比較和執行的100倍工作數據。如何重構數組之間的複製/移動數據?

我有150個以上的陣列,所以150倍:

// for each array 
    SetLength(myData[Idx].WorkNames,Length(tmpNames)); // <- prepare to copy 
    for i := 0 to High(tmpNames) do // <- copy 
     myData[Idx].WorkNames[i]:=tmpNames[i]; 
    SetLength(tmpNames,0); // <- clear tmp array 

4行代碼對於每個陣列 - 150x4 = 600 LOC +初始+空行 - 大約900 LOC

這裏是我做的例子:

type 

    TName = record 
    NameID:integer; 
    Description:string; 
    end; 

    TItem = record 
    ItemID:integer; 
    Description:string; 
    Active:boolean; 
    end; 

    TWorkData = record 
     WorkDataType:string; 
     WorkNames:array of TName; 
     WorkItems:array of TItem; 
    end; 

var 

    AllWorkData:array of TWorkData; // <- global array that has all work data - up to 100x sets of work data 
    tmpNames:array of TName; // <- tmp arrays before saving to work array 
    tmpItems:array of TItem; // 

procedure TForm1.Button1Click(Sender: TObject); 
var i,Idx:integer; 
begin 

    // 1. read data into tmp arrays 
    ReadDataIntoTmpArrays; 
    ProcessTmpData; 

    // 2. copy tmp arrays into work data 
    Idx:=GetWorkDataIdx; // <- work data sequence number; start with 0 
    AllWorkData[Idx].WorkDataType:=GetWorkDataName(Idx); 
    SetLength(AllWorkData[Idx].WorkNames,Length(tmpNames)); 
    SetLength(AllWorkData[Idx].WorkItems,Length(tmpItems)); 

    for i := 0 to High(tmpNames) do 
    AllWorkData[Idx].WorkNames[i]:=tmpNames[i]; 

    for i := 0 to High(tmpItems) do 
    AllWorkData[Idx].WorkItems[i]:=tmpItems[i]; 

    // 3. clear tmp arrays 
    SetLength(tmpNames,0); 
    SetLength(tmpItems,0); 

end; 

問:有什麼我能做到這一點更容易維護,重構代碼?

回答

1

如果你真的想複製,那麼使用泛型。你可以從在System.Generics.Collections中聲明的TArray類的靜態類方法派生。例如:

type 
    TArray = class(Generics.Collections.TArray) 
    public 
    class function Copy<T>(const Source: array of T; Index, Count: Integer): TArray<T>; overload; static; 
    class function Copy<T>(const Source: array of T): TArray<T>; overload; static; 
    end; 

.... 

class function TArray.Copy<T>(const Source: array of T; Index, Count: Integer): TArray<T>; 
var 
    i: Integer; 
begin 
    SetLength(Result, Count); 
    for i := 0 to high(Result) do begin 
    Result[i] := Source[i+Index]; 
    end; 
end; 

class function TArray.Copy<T>(const Source: array of T): TArray<T>; 
var 
    i: Integer; 
begin 
    SetLength(Result, Length(Source)); 
    for i := 0 to high(Result) do begin 
    Result[i] := Source[i]; 
    end; 
end; 

注意,上述所有要求你停止使用array of TMyType,而開始使用通用動態數組TArray<TMyType>

在你的情況下,雖然你太過複雜。替換:

SetLength(myData[Idx].WorkNames,Length(tmpNames)); // <- prepare to copy 
for i := 0 to High(tmpNames) do // <- copy 
    myData[Idx].WorkNames[i]:=tmpNames[i]; 
SetLength(tmpNames,0); // <- clear tmp array 

有:

myData[Idx].WorkNames := tmpNames; 
tmpNames := nil; 

如果你是準備讓tmpNames乾脆離開的範圍,那麼你可以使用一個線:

myData[Idx].WorkNames := tmpNames; 

儘管如此,如果tmpNames是重用於不同的陣列,則需要nil分配。

然後,就我所見問題中的代碼而言,根本不需要臨時數組。爲什麼不直接在長壽命的數據結構上運行。

這些數組賦值只有在賦值的源和目標是賦值兼容的情況下才是允許的。你的類型不是因爲你使用了不同的類型。切換到TArray<T>以避免這種情況。看到這個問題更多:Why are two seemingly identical dynamic array types deemed not assignment compatible?

請記住,動態數組是引用類型。在這裏顯示的用法中,您只需複製參考。您只需要實際陣列的一個實例。所以根本不需要複製。

+0

這行'AllWorkData [0] .WorkNames:= tmpNames;'說:'[dcc32錯誤] Unit1.pas(90):E2008 Incompatible types'。我究竟做錯了什麼? –

+0

這是因爲.'WorkNames'和'tmpNames'是不屬於賦值兼容的不同類型。改用'TArray '代替'T'的適當類型。 –

+0

啊哈,現在有用。所以,你建議用'TArray '替換所有'T'陣列...... –

相關問題