我有这样的备忘录:
Mahogany
Unpolished
In Stock : Yes
Total Stock : 102
Redwood
Polished
In Stock : Yes
Total Stock : 80
Pine
Polished
In Stock : Yes
Total Stock : 22
我想只拥有Redwood的Total Stock。
有很多相同的字符串总库存
我不能将此字符串用作我的关键字。所以,我使用“Redwood”,但我不知道如何在“Redwood”之后获得“Total Stock”这一行。
var
i: Integer;
s: string;
begin
for i := 0 to mem0.lines.Count - 1 do
begin
if (AnsiContainsStr(mem0.lines[i], 'Redwood')) then
begin
// s:= Redwood's total stock, how to do this ?
end
end;
end;
答案 0 :(得分:3)
缺少的代码是:
s := mem0.Lines[i+3];
这假设数据的格式始终与问题中的完全一致。如果该假设有效,则这个简单的代码是最佳解决方案。
使用具有良好解析器和发射器的标准人类可读结构化数据格式(如JSON或YAML)可能更有意义。遗憾的是,对Delphi上的YAML的支持基本上是不存在的,因此留下了JSON。
答案 1 :(得分:3)
你可以试试这个,但就像你原来的代码一样,它有点“脆弱”。因为它假设您正在搜索的文本的布局(特别是您正在搜索的文本打包在TStrings对象中):
function TotalForItem(const ItemName : String; Strings : TStrings) : String;
var
i,
j,
p : Integer;
s : string;
TotalLineIntro : String;
begin
Result := '';
TotalLineIntro := 'Total Stock : ';
for i := 0 to Strings.Count - 1 do
begin
if (Pos(ItemName, Strings[i]) > 0) then
begin
for j:= i + 1 to Strings.Count - 1 do begin
p := Pos(TotalLineIntro, Strings[j]);
if p > 0 then
begin
Result := Copy(Strings[j], p + Length(TotalLineIntro), Length(Strings[j]));
exit;
end;
end;
end
end;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
ShowMessage(TotalForItem('Redwood', Memo1.Lines));
end;
答案 2 :(得分:2)
而不是AnsiContainsStr
,您可以使用StartsWith
,因为Redwood部分的其余部分都是indentend。
var
I: Integer;
TotalStockLine: string;
MyArray: TArray<string>
begin
for I := 0 to Memo1.Lines.Count - 1 do
if Memo.Lines[I].StartsWith('Redwood') then
begin
TotalStockLine := Trim(Memo.Lines[I + 3];
Break;
end;
if TotalStockLine <> '' then
begin
MyArray := TotalStockLine.Split([':']);
TotalStock := StrToInt(Trim(MyArray[1]));
end;
等......这可能会简化一点,但这表明你可以做到这一点。
FWIW,这假设您使用的是XE3或更高版本。否则,您必须使用独立的StartsWith
。