ListView 重复第二个 TListItem.Caption 的项目
ListView repeating items from second TListItem.Caption
我有两个 StringList
分别加载(从文件)用户和用户 + 密码。我正在比较这些列表以确定(第一个列表的)哪个用户已经有密码(在第二个列表中),然后插入 ListView
谁有密码,谁还没有密码。
但是这里存在一个问题,从第二个 ListItem.Caption
(用户)开始重复两次。
我该如何解决这个问题?
我加载到列表中的文件是:
users.dat
- 用户 01
- 用户 02
- 用户 03
logins.dat
- User01|test01
- User01|test01
这是我最后一次尝试代码:
type
TForm1 = class(TForm)
Button1: TButton;
ListView1: TListView;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
L1, L2, LSplit: TStringList;
L: TListItem;
I, J: Integer;
begin
L1 := TStringList.Create;
L2 := TStringList.Create;
LSplit := TStringList.Create;
L1.LoadFromFile('users.dat');
L2.LoadFromFile('logins.dat');
for I := 0 to L1.Count - 1 do
begin
for J := 0 to L2.Count - 1 do
begin
LSplit.Clear;
ExtractStrings(['|'], [], PChar(L2[J]), LSplit);
if L1[I] = LSplit[0] then
begin
L := ListView1.Items.Add;
L.Caption := LSplit[0];
L.SubItems.Add(LSplit[1]);
Break;
end;
L := ListView1.Items.Add;
L.Caption := L1[I];
end;
end;
L1.Free;
L2.Free;
LSplit.Free;
end;
end.
for I := 0 to L1.Count - 1 do
begin
found := false;
L := ListView1.Items.Add;
for J := 0 to L2.Count - 1 do
begin
LSplit.Clear;
ExtractStrings(['|'], [], PChar(L2[J]), LSplit);
if L1[I] = LSplit[0] then
begin
L.Caption := LSplit[0];
L.SubItems.Add(LSplit[1]);
found := true;
Break;
end;
end;
if not found then
L.Caption := L1[I];
end;
另请注意,字典方法对于大型列表来说要快得多
你的内循环坏了。即使正在比较的 2 个 StringList 项目彼此不匹配,它也会向 ListView 添加项目。对于第一个列表中的每个用户,您将其添加到 ListView 的次数与第二个列表中条目的次数一样多。
您的代码应该看起来更像这样:
procedure TForm1.Button1Click(Sender: TObject);
var
L1, L2, LSplit: TStringList;
L: TListItem;
I, J: Integer;
begin
L1 := TStringList.Create;
try
L2 := TStringList.Create;
try
LSplit := TStringList.Create;
try
L1.LoadFromFile('users.dat');
L2.LoadFromFile('logins.dat');
for I := 0 to L1.Count - 1 do
begin
L := ListView1.Items.Add;
L.Caption := L1[I];
for J := 0 to L2.Count - 1 do
begin
LSplit.Clear;
ExtractStrings(['|'], [], PChar(L2[J]), LSplit);
if L1[I] = LSplit[0] then
begin
L.SubItems.Add(LSplit[1]);
Break;
end;
end;
end;
finally
LSplit.Free;
end;
finally
L2.Free;
end;
finally
L1.Free;
end;
end;
也就是说,您不需要 3 个 TStringList
对象和 2 个循环。 2 TStringList
个对象和 1 个循环就足够了:
procedure TForm1.Button1Click(Sender: TObject);
var
L1, L2: TStringList;
L: TListItem;
I: Integer;
begin
L1 := TStringList.Create;
try
L2 := TStringList.Create;
try
L1.LoadFromFile('users.dat');
L2.LoadFromFile('logins.dat');
L2.NameValueSeparator := '|';
for I := 0 to L1.Count - 1 do
begin
L := ListView1.Items.Add;
L.Caption := L1[I];
L.SubItems.Add(L2.Values[L1[I]]);
end;
finally
L2.Free;
end;
finally
L1.Free;
end;
end;
您的代码的问题是您总是将第一个列表中的用户名添加到结果中,而不管您是否已经从第二个列表中添加了包含密码的用户名或没有。
为避免这种情况,您需要以一种方式编写代码,即只有在第二个列表中未添加用户名时,才会从第一个列表中添加用户名。
//If password exist in second list add username and password from second list
if L1[I] = LSplit[0] then
begin
L := ListView1.Items.Add;
L.Caption := LSplit[0];
L.SubItems.Add(LSplit[1]);
Break;
end
//Else add username from first list
else
begin
L := ListView1.Items.Add;
L.Caption := L1[I];
end;
另请注意,如果您的第二个列表包含第一个列表中不存在的用户名,您的应用程序将失败。
例如让我们检查下一个场景:
users.dat
- 用户 01
- 用户 02
- 用户 03
logins.dat
- User01|test01
- User02|test01
- User04|test04
在上述情况下,您的最终结果将不包含来自 User04 的任何数据,因为它不存在于您的第一个列表中。
因此,我建议您使用不同的方法来迭代第二个列表,并为每个条目搜索第一个列表以查看用户名是否存在于其中。
如果确实如此,您可以编辑第一个列表中的条目以添加第二个列表中的密码信息。如果您在第一个列表中找不到用户名,则可以在其中添加用户名和密码。
这将向您保证最终结果将排除两个列表中的所有用户名,无论它们是在哪个列表中找到的。
我有两个 StringList
分别加载(从文件)用户和用户 + 密码。我正在比较这些列表以确定(第一个列表的)哪个用户已经有密码(在第二个列表中),然后插入 ListView
谁有密码,谁还没有密码。
但是这里存在一个问题,从第二个 ListItem.Caption
(用户)开始重复两次。
我该如何解决这个问题?
我加载到列表中的文件是:
users.dat
- 用户 01
- 用户 02
- 用户 03
logins.dat
- User01|test01
- User01|test01
这是我最后一次尝试代码:
type
TForm1 = class(TForm)
Button1: TButton;
ListView1: TListView;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
L1, L2, LSplit: TStringList;
L: TListItem;
I, J: Integer;
begin
L1 := TStringList.Create;
L2 := TStringList.Create;
LSplit := TStringList.Create;
L1.LoadFromFile('users.dat');
L2.LoadFromFile('logins.dat');
for I := 0 to L1.Count - 1 do
begin
for J := 0 to L2.Count - 1 do
begin
LSplit.Clear;
ExtractStrings(['|'], [], PChar(L2[J]), LSplit);
if L1[I] = LSplit[0] then
begin
L := ListView1.Items.Add;
L.Caption := LSplit[0];
L.SubItems.Add(LSplit[1]);
Break;
end;
L := ListView1.Items.Add;
L.Caption := L1[I];
end;
end;
L1.Free;
L2.Free;
LSplit.Free;
end;
end.
for I := 0 to L1.Count - 1 do
begin
found := false;
L := ListView1.Items.Add;
for J := 0 to L2.Count - 1 do
begin
LSplit.Clear;
ExtractStrings(['|'], [], PChar(L2[J]), LSplit);
if L1[I] = LSplit[0] then
begin
L.Caption := LSplit[0];
L.SubItems.Add(LSplit[1]);
found := true;
Break;
end;
end;
if not found then
L.Caption := L1[I];
end;
另请注意,字典方法对于大型列表来说要快得多
你的内循环坏了。即使正在比较的 2 个 StringList 项目彼此不匹配,它也会向 ListView 添加项目。对于第一个列表中的每个用户,您将其添加到 ListView 的次数与第二个列表中条目的次数一样多。
您的代码应该看起来更像这样:
procedure TForm1.Button1Click(Sender: TObject);
var
L1, L2, LSplit: TStringList;
L: TListItem;
I, J: Integer;
begin
L1 := TStringList.Create;
try
L2 := TStringList.Create;
try
LSplit := TStringList.Create;
try
L1.LoadFromFile('users.dat');
L2.LoadFromFile('logins.dat');
for I := 0 to L1.Count - 1 do
begin
L := ListView1.Items.Add;
L.Caption := L1[I];
for J := 0 to L2.Count - 1 do
begin
LSplit.Clear;
ExtractStrings(['|'], [], PChar(L2[J]), LSplit);
if L1[I] = LSplit[0] then
begin
L.SubItems.Add(LSplit[1]);
Break;
end;
end;
end;
finally
LSplit.Free;
end;
finally
L2.Free;
end;
finally
L1.Free;
end;
end;
也就是说,您不需要 3 个 TStringList
对象和 2 个循环。 2 TStringList
个对象和 1 个循环就足够了:
procedure TForm1.Button1Click(Sender: TObject);
var
L1, L2: TStringList;
L: TListItem;
I: Integer;
begin
L1 := TStringList.Create;
try
L2 := TStringList.Create;
try
L1.LoadFromFile('users.dat');
L2.LoadFromFile('logins.dat');
L2.NameValueSeparator := '|';
for I := 0 to L1.Count - 1 do
begin
L := ListView1.Items.Add;
L.Caption := L1[I];
L.SubItems.Add(L2.Values[L1[I]]);
end;
finally
L2.Free;
end;
finally
L1.Free;
end;
end;
您的代码的问题是您总是将第一个列表中的用户名添加到结果中,而不管您是否已经从第二个列表中添加了包含密码的用户名或没有。
为避免这种情况,您需要以一种方式编写代码,即只有在第二个列表中未添加用户名时,才会从第一个列表中添加用户名。
//If password exist in second list add username and password from second list
if L1[I] = LSplit[0] then
begin
L := ListView1.Items.Add;
L.Caption := LSplit[0];
L.SubItems.Add(LSplit[1]);
Break;
end
//Else add username from first list
else
begin
L := ListView1.Items.Add;
L.Caption := L1[I];
end;
另请注意,如果您的第二个列表包含第一个列表中不存在的用户名,您的应用程序将失败。
例如让我们检查下一个场景: users.dat
- 用户 01
- 用户 02
- 用户 03
logins.dat
- User01|test01
- User02|test01
- User04|test04
在上述情况下,您的最终结果将不包含来自 User04 的任何数据,因为它不存在于您的第一个列表中。
因此,我建议您使用不同的方法来迭代第二个列表,并为每个条目搜索第一个列表以查看用户名是否存在于其中。
如果确实如此,您可以编辑第一个列表中的条目以添加第二个列表中的密码信息。如果您在第一个列表中找不到用户名,则可以在其中添加用户名和密码。
这将向您保证最终结果将排除两个列表中的所有用户名,无论它们是在哪个列表中找到的。