【问题标题】:Delphi compare 2 stringlists by substring search and merge the matching items in another stringlistDelphi通过子字符串搜索比较2个字符串列表并将匹配项合并到另一个字符串列表中
【发布时间】:2018-06-23 07:42:00
【问题描述】:

我正在尝试通过子字符串搜索来比较 2 个字符串列表,并将找到的项目匹配到另一个字符串列表中。

“Stringlist_SCSILogicalUnit”包含如下数据:

SCSIBus=0;SCSILogicalUnit=0;SCSIPort=1;SCSITargetId=0;Status=OK
SCSIBus=0;SCSILogicalUnit=1;SCSIPort=2;SCSITargetId=0;Status=OK
SCSIBus=0;SCSILogicalUnit=2;SCSIPort=2;SCSITargetId=0;Status=OK
SCSIBus=0;SCSILogicalUnit=3;SCSIPort=2;SCSITargetId=0;Status=OK
SCSIBus=0;SCSILogicalUnit=4;SCSIPort=2;SCSITargetId=0;Status=OK
SCSIBus=0;SCSILogicalUnit=43;SCSIPort=2;SCSITargetId=0;Status=OK
SCSIBus=0;SCSILogicalUnit=44;SCSIPort=2;SCSITargetId=0;Status=OK
SCSIBus=0;SCSILogicalUnit=45;SCSIPort=2;SCSITargetId=0;Status=OK
SCSIBus=0;SCSILogicalUnit=46;SCSIPort=2;SCSITargetId=0;Status=OK

“Stringlist_LUN”包含如下数据:

  LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 67
;
    LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 43
;
    LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 44
;
    LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 45
;
    LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 50
;
    LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 51
;

我需要匹配“LUN”值和“SCSILogicalUnit”值之间的对应关系(LUN 和 SCSILogicalUnit 具有相同的值 Lun=SCSILogicalUnit),以便在“Stringlist_result”中监听结果。 结果应该看起来像

"SCSIBus=0;SCSILogicalUnit=46;SCSIPort=2;SCSITargetId=0;Status=OK =>>> LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 46
;"

我正在使用以下函数但结果不一致:

function stringlist_mmg_FastJoin(List1, List2: TStringList): TStringList;
var
  L1Idx, L2Idx,
  L1Max, L2Max: Integer;
  v: Integer;
begin
  // Create Result list, set it's min size
  Result := TStringList.Create;
  Result.Capacity := Max(List1.Count, List2.Count);
  // limits
  L1Idx := 0;
  L2Idx := 0;
  L1Max := List1.Count;
  L2Max := List2.Count;
  // forse sort
  List1.Sorted := True;
  List2.Sorted := True;

  // iterate
  while (L1Idx<L1Max) and (L2Idx<L2Max) do
  begin

if pos(extracttextbetween(List1[L1idx],'SCSILogicalUnit=',';'),List2[L2idx])>1  then


    begin
      Result.Add(List1[L1Idx]+' = '+List2[L2idx]);
      Inc(L1Idx);
      Inc(L2Idx);
    end

    else if v < 0 then                              // Add from List 1
    begin
      //Result.Add(List1[L1Idx]);
      Inc(L1Idx);
    end
    else // v > 0                                   // Add from List 2
    begin
      //Result.Add(List2[L2Idx]);
      Inc(L2Idx);
    end;
  end;
  // Add all remainders from second list
  while L2Idx < L2Max do
  begin
    //Result.Add(List2[L2Idx]);
    Inc(L2Idx);

  end;
  end;



stringlist_resultat:=Tstringlist.create;
stringlist_rezultat.addstrings(stringlist_mmg_FastJoin(Stringlist_SCSILogicalUnit,stringlist_LUN));

结果应该是:

PNPDeviceID=MPIOSCSIBus=0;SCSILogicalUnit=67;SCSIPort=2;SCSITargetId=0;Status=OK =>>>     LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 67
;

当我运行这个函数时,我得到一个单一的结果。

有人可以告诉我我做错了什么吗? 这个任务可以在没有字符串列表的情况下优化吗?

谢谢!

【问题讨论】:

  • 你应该使用字典来解决这个问题。将这两个文件解析为以 Lum 值为键的字典。
  • 您能举个例子吗?
  • 没有真正的动机去做那件事。各个部分都有很多示例。
  • 此外,Delphi 2010 很古老,它的通用集合有点不稳定。尽管它们对于这个简单的任务可能工作得很好。如果我是你,我会用正则表达式解析,剩下的应该用字典。一旦你有了合适的工具,代码大部分是自己编写的,你就可以扔掉你在这里拥有的很多东西。
  • 50 次代表可能不足以激励任何人。这只是对一个体面问题的一个很好的回答。这样做对我们来说更有趣。

标签: delphi delphi-2010 tstringlist


【解决方案1】:

将其重命名为仅加入,不能声称它的快速..

function stringlist_mmg_Join(const LogicalUnitList, LUNList: TStringList): TStringList;
const NotFound = -1;

  function ExtractTextBetween(const Txt, StartTag, EndTag : string; out iValue : integer): Boolean;
  var
    value : string;
    iStartTag, iEndTag : integer;
  begin
    Result := False;

    iStartTag := Pos(StartTag, Txt);
    if (iStartTag = NotFound) then Exit;

    iEndTag := PosEx(EndTag, Txt, iStartTag);
    if (iEndTag = NotFound) then Exit;

    Inc(iStartTag, Length(StartTag));
    Value := MidStr(Txt, iStartTag, iEndTag-iStartTag);
    Result := TryStrToInt(Value, iValue);
  end;

var
  i, v, ix: Integer;
begin
  Result := TStringList.Create;

  // iterate, Parse and write Value as Object
  for i := 0 to LogicalUnitList.Count - 1 do begin
     If ExtractTextBetween(LogicalUnitList[i], 'SCSILogicalUnit=', ';', v) then begin
       LogicalUnitList.Objects[i] := Pointer(V+1);
     end;
  end;

  // iterate, Parse and write Value as Object
  for i := 0 to LUNList.Count - 1 do begin
     If ExtractTextBetween(LUNList[i] + ';', 'LUN ', ';', v) then begin
       LUNList.Objects[i] := Pointer(V+1);
     end;
  end;

  // Match
  for i := 0 to LogicalUnitList.Count - 1 do begin
    ix := LUNList.IndexOfObject(LogicalUnitList.Objects[i]);
    if (ix = NotFound) then Continue;
    Result.Add(LogicalUnitList[i] + '  =>>>' + LUNList[ix] + ';');
  end;
end;

输出是:

SCSIBus=0;SCSILogicalUnit=43;SCSIPort=2;SCSITargetId=0;Status=OK  =>>>    LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 43;
SCSIBus=0;SCSILogicalUnit=44;SCSIPort=2;SCSITargetId=0;Status=OK  =>>>    LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 44;
SCSIBus=0;SCSILogicalUnit=45;SCSIPort=2;SCSITargetId=0;Status=OK  =>>>    LocationInformation    REG_SZ    Port(2,2,3,3) Bus 0, Target ID 0, LUN 45;

【讨论】:

  • 这个函数的结果是错误的:SCSIBus=0;SCSILogicalUnit=0;SCSIPort=2;SCSITargetId=0;Status=OK =>>> Port(2,2,3,3) Bus 0, Target ID 0, LUN 67 它匹配 SCSILogicalUnit=0 到 LUN 67 ;;
  • 谢谢弗雷德!这完美地工作。你应该得到赏金!
猜你喜欢
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-11
  • 2020-11-27
  • 1970-01-01
  • 2023-03-28
相关资源
最近更新 更多