如何提取唯一字符串的第一个实例
How to extract the first instance of unique strings
我需要从 12 年来一直由计算机生成的每天一个文本文件中提取独特项目的列表。文件名仅因包含日期而异,因此很容易在代码中生成所需的名称。它们包括在给定日期内我当地机场的所有飞机起降的列表,按时间顺序排列。自然,同一架飞机来来去去很多次,objective就是循环文件,挑出每架飞机出现的第一个实例(第一次访问或FV)复制到列表中,然后从此忽略它。结果应该是按日期顺序排列的所有首次访问的列表。应该很简单,但是...我的程序很小,所以我包含了整个实现代码。
procedure TForm1.FormCreate(Sender: TObject);
begin
FileDate := StrToDate('01/01/2007');
FName := 'E:LGW Reports/SBSLGW2007-01-01.txt'; //1st file to be read
FDStr := copy(FName, 21, 10);
TempList := TStringList.Create; //temp holder for file contents
FVCheckList := TStringList.Create; //holds unique identifier (UID)
FVCheckList.Sorted := TRUE;
FVCheckList.Duplicates := dupIgnore;
FVList:= TStringList.Create; //the main output
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
Memo1.Lines.Append('Started');
Repeat
TempList.Clear;
TempList.LoadFromFile(FName);
for i := 1 to TempList.Count-1 do
begin
Line := TempList.Strings[i];
//create a //create a Unique identifier (UID) from elements in Line
Serial := Trim(Copy(Line, 22, 9));
MsnPos1 := Pos('[', Line) + 1;
MsnPos2 := Pos(']', Line);
Msn := copy(Line, MsnPos1, (MsnPos2 - MsnPos1));
UID := Serial + '/' + Msn;
//
if (FVCheckList.IndexOf(UID) < 0) then
begin
FVCheckList.Append(UID);
//Add date of file to Line, otherwise it gives no clue when FV was
FVList.Append(FormatDateTime('YYYY-MM-DD', FileDate) + ' ' + Line);
FileDate := IncDay(FileDate, 1);
FName := 'E:LGW Reports/SBSLGW' + FormatDateTime('YYYY-MM-DD', FileDate) + '.txt';
end;
end;
Until FileExists(FName) = FALSE;
FVCheckList.SaveToFile('E:LGW Reports/First Visit Checklist.txt');
FVList.SaveToFile('E:LGW Reports/First Visits.txt');
Memo1.Lines.Append('Finished');
Memo1.Lines.SaveToFile('E:LGW Reports/Files parsed.txt');
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
TempList.Free;
FVCheckList.Free;
FVList.Free;
end;
没有编译器错误,它在几秒钟内运行完成并生成指定的两个文本文件,格式正确。最大的问题是 FVList 中实际列出的行 而不是 始终是飞机的第一次访问,它们可能是第一次、最近或介于两者之间。关于为什么会出现错误的实例,我看不到任何明显的线索:如果我的代码是正确的,那么 TStringList FVCheckList 的功能有问题。错误更有可能是我忽略的东西,或者我对 .dupIgnore 工作原理的理解,或者我的循环没有按预期工作。
如果有任何实际帮助,我将不胜感激。非常感谢。
Repeat
...
Until FileExists(FName) = FALSE;
应该是
While FileExists(FName) = TRUE do
Begin
End;
如果第一个 2007-01-01
文件不存在,您的代码将在第一个 LoadFromFile()
时崩溃,因为您在加载文件之前不检查文件是否存在,这与后续文件不同。
否则,我建议坚持使用 repeat
,但在每次循环迭代的顶部分配 FName
,而不是在循环外初始化它,然后在每次迭代的底部重新分配。无需重复努力。
如果您手动勾选 IndexOf()
,则根本不需要使用 Sorted
或 dupIgnore
。这是你在这种情况下应该做的。当 dupIgnore
忽略一个新字符串时,Append()
不会告诉您该字符串已被忽略。为此,您必须检查 Count
是否实际增加了。
在外循环中,FileDate
和FName
的重新赋值应该在for
内循环之外,而不是在for
循环之内。
试试这个:
procedure TForm1.FormCreate(Sender: TObject);
begin
FileDate := EncodeDate(2007,1,1);
FDStr := FormatDateTime('YYYY-MM-DD', FileDate);
TempList := TStringList.Create; //temp holder for file contents
FVCheckList := TStringList.Create; //holds unique identifier (UID)
FVList := TStringList.Create; //the main output
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
Memo1.Lines.Append('Started');
Repeat
FName := 'E:LGW Reports/SBSLGW' + FormatDateTime('YYYY-MM-DD', FileDate) + '.txt';
if not FileExists(FName) then Break;
Memo1.Lines.Append(FName)
TempList.LoadFromFile(FName);
for i := 1 to TempList.Count-1 do
begin
Line := TempList.Strings[i];
//create a Unique identifier (UID) from elements in Line
Serial := Trim(Copy(Line, 22, 9));
MsnPos1 := Pos('[', Line) + 1;
MsnPos2 := PosEx(']', Line, MsnPos1);
Msn := copy(Line, MsnPos1, (MsnPos2 - MsnPos1));
UID := Serial + '/' + Msn;
if FVCheckList.IndexOf(UID) = -1 then
begin
FVCheckList.Append(UID);
//Add date of file to Line, otherwise it gives no clue when FV was
FVList.Append(FormatDateTime('YYYY-MM-DD', FileDate) + ' ' + Line);
end;
end;
FileDate := IncDay(FileDate, 1);
end;
FVCheckList.SaveToFile('E:LGW Reports/First Visit Checklist.txt');
FVList.SaveToFile('E:LGW Reports/First Visits.txt');
Memo1.Lines.Append('Finished');
Memo1.Lines.SaveToFile('E:LGW Reports/Files parsed.txt');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
TempList.Free;
FVCheckList.Free;
FVList.Free;
end;
我需要从 12 年来一直由计算机生成的每天一个文本文件中提取独特项目的列表。文件名仅因包含日期而异,因此很容易在代码中生成所需的名称。它们包括在给定日期内我当地机场的所有飞机起降的列表,按时间顺序排列。自然,同一架飞机来来去去很多次,objective就是循环文件,挑出每架飞机出现的第一个实例(第一次访问或FV)复制到列表中,然后从此忽略它。结果应该是按日期顺序排列的所有首次访问的列表。应该很简单,但是...我的程序很小,所以我包含了整个实现代码。
procedure TForm1.FormCreate(Sender: TObject);
begin
FileDate := StrToDate('01/01/2007');
FName := 'E:LGW Reports/SBSLGW2007-01-01.txt'; //1st file to be read
FDStr := copy(FName, 21, 10);
TempList := TStringList.Create; //temp holder for file contents
FVCheckList := TStringList.Create; //holds unique identifier (UID)
FVCheckList.Sorted := TRUE;
FVCheckList.Duplicates := dupIgnore;
FVList:= TStringList.Create; //the main output
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
Memo1.Lines.Append('Started');
Repeat
TempList.Clear;
TempList.LoadFromFile(FName);
for i := 1 to TempList.Count-1 do
begin
Line := TempList.Strings[i];
//create a //create a Unique identifier (UID) from elements in Line
Serial := Trim(Copy(Line, 22, 9));
MsnPos1 := Pos('[', Line) + 1;
MsnPos2 := Pos(']', Line);
Msn := copy(Line, MsnPos1, (MsnPos2 - MsnPos1));
UID := Serial + '/' + Msn;
//
if (FVCheckList.IndexOf(UID) < 0) then
begin
FVCheckList.Append(UID);
//Add date of file to Line, otherwise it gives no clue when FV was
FVList.Append(FormatDateTime('YYYY-MM-DD', FileDate) + ' ' + Line);
FileDate := IncDay(FileDate, 1);
FName := 'E:LGW Reports/SBSLGW' + FormatDateTime('YYYY-MM-DD', FileDate) + '.txt';
end;
end;
Until FileExists(FName) = FALSE;
FVCheckList.SaveToFile('E:LGW Reports/First Visit Checklist.txt');
FVList.SaveToFile('E:LGW Reports/First Visits.txt');
Memo1.Lines.Append('Finished');
Memo1.Lines.SaveToFile('E:LGW Reports/Files parsed.txt');
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
TempList.Free;
FVCheckList.Free;
FVList.Free;
end;
没有编译器错误,它在几秒钟内运行完成并生成指定的两个文本文件,格式正确。最大的问题是 FVList 中实际列出的行 而不是 始终是飞机的第一次访问,它们可能是第一次、最近或介于两者之间。关于为什么会出现错误的实例,我看不到任何明显的线索:如果我的代码是正确的,那么 TStringList FVCheckList 的功能有问题。错误更有可能是我忽略的东西,或者我对 .dupIgnore 工作原理的理解,或者我的循环没有按预期工作。
如果有任何实际帮助,我将不胜感激。非常感谢。
Repeat
...
Until FileExists(FName) = FALSE;
应该是
While FileExists(FName) = TRUE do
Begin
End;
如果第一个 2007-01-01
文件不存在,您的代码将在第一个 LoadFromFile()
时崩溃,因为您在加载文件之前不检查文件是否存在,这与后续文件不同。
否则,我建议坚持使用 repeat
,但在每次循环迭代的顶部分配 FName
,而不是在循环外初始化它,然后在每次迭代的底部重新分配。无需重复努力。
如果您手动勾选 IndexOf()
,则根本不需要使用 Sorted
或 dupIgnore
。这是你在这种情况下应该做的。当 dupIgnore
忽略一个新字符串时,Append()
不会告诉您该字符串已被忽略。为此,您必须检查 Count
是否实际增加了。
在外循环中,FileDate
和FName
的重新赋值应该在for
内循环之外,而不是在for
循环之内。
试试这个:
procedure TForm1.FormCreate(Sender: TObject);
begin
FileDate := EncodeDate(2007,1,1);
FDStr := FormatDateTime('YYYY-MM-DD', FileDate);
TempList := TStringList.Create; //temp holder for file contents
FVCheckList := TStringList.Create; //holds unique identifier (UID)
FVList := TStringList.Create; //the main output
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
Memo1.Lines.Append('Started');
Repeat
FName := 'E:LGW Reports/SBSLGW' + FormatDateTime('YYYY-MM-DD', FileDate) + '.txt';
if not FileExists(FName) then Break;
Memo1.Lines.Append(FName)
TempList.LoadFromFile(FName);
for i := 1 to TempList.Count-1 do
begin
Line := TempList.Strings[i];
//create a Unique identifier (UID) from elements in Line
Serial := Trim(Copy(Line, 22, 9));
MsnPos1 := Pos('[', Line) + 1;
MsnPos2 := PosEx(']', Line, MsnPos1);
Msn := copy(Line, MsnPos1, (MsnPos2 - MsnPos1));
UID := Serial + '/' + Msn;
if FVCheckList.IndexOf(UID) = -1 then
begin
FVCheckList.Append(UID);
//Add date of file to Line, otherwise it gives no clue when FV was
FVList.Append(FormatDateTime('YYYY-MM-DD', FileDate) + ' ' + Line);
end;
end;
FileDate := IncDay(FileDate, 1);
end;
FVCheckList.SaveToFile('E:LGW Reports/First Visit Checklist.txt');
FVList.SaveToFile('E:LGW Reports/First Visits.txt');
Memo1.Lines.Append('Finished');
Memo1.Lines.SaveToFile('E:LGW Reports/Files parsed.txt');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
TempList.Free;
FVCheckList.Free;
FVList.Free;
end;