本帖最后由 YINLINGWO 于 2009-09-20 22:37:27 编辑

解决方案 »

  1.   


      for i:= 0 to BigNo.Count-1  do
        begin
          if ListBox1.Items.IndexOf(BigNo.Strings[i]) <> -1 then
            begin
              BigNo.Strings[i]:=' ';
            end;
        end;
      for I := 0 to BigNo.Count- 1 do
        begin
          strl:=strl+bigno.Strings[i];
        end;变成下面的,可以减少一次循环  for i:= 0 to BigNo.Count-1  do
        begin
          if ListBox1.Items.IndexOf(BigNo.Strings[i]) <> -1 then
            begin
              BigNo.Strings[i]:=' ';
            end;
          strl:=strl+bigno.Strings[i];
        end;
      

  2.   

    for I :=strtoint(LabeledEdit1.Text) to StrToInt(LabeledEdit2.Text) do
        begin
          BigNo.Add(IntToStr(i));
        end;  for i:= 0 to BigNo.Count-1  do
        begin
          if ListBox1.Items.IndexOf(BigNo.Strings[i]) <> -1 then
            begin
              BigNo.Strings[i]:=' ';
            end;
        end;
      for I := 0 to BigNo.Count- 1 do
        begin
          strl:=strl+bigno.Strings[i];
        end;最起码这3个循环都可以合并,可能下面的一个循环也可以合并并且可以用线程来循环,随时发消息给窗口循环的进度。
    还有你的需求是不是一定要全部循环完,是不是可以在满足一定的条件下退出循环等等。
      

  3.   

      for i:=0 to sl.Count-1  do
        begin
             if trim(sl.Strings[i]) = '' then
            sl.Delete(i)假死很大程度出现在这个循环里,当DELETE一个个,你的SL的COUNT就变了打个比方:SL[3] -> ''
    SL[4] -> ''
    SL[5] -> '234'DELETE SL[3],循环 I 跑到4.COUNT也变成SL[3] -> ''
    SL[4] -> '234'  跑到4的时候,SL[3]就不处理了 所以应该是从最大到最小即 SOMEVALUE:= sl.Count-1; 定死先for somevalue downto 0 do ...
      

  4.   

    1: 数字比字符串快,所以:
    for I :=strtoint(LabeledEdit1.Text) to StrToInt(LabeledEdit2.Text) do
      BigNo.Add(IntToStr(i));
    根本没必要,直接用两个StartNO, EndNO保存就可以了,不用TStrings.Add
    2: 判断一个数字在一个范围内,需要用这个方法吗?
    if ListBox1.Items.IndexOf(BigNo.Strings[i]) <> -1 then3:
    if trim(sl.Strings[i]) = '' then
      sl.Delete(i)
    sl删除一个项,要用for I := sl.count - 1 downto 0其它不说了。
      

  5.   


    看高手说的有条有理,我是初学DELPHI 有很多方法都和思路都还不知道
    望高手能够仔细讲解一下上面的内容,谢谢
      

  6.   

    还有一个,你的数据有这么大,最好是用数据库来存数据啦,在数据库里查询也很快啦, 
    一句 not in ... 就搞掂了!!!强烈建议用数据库!!!
      

  7.   

    for I :=strtoint(LabeledEdit1.Text) to StrToInt(LabeledEdit2.Text) do
    一、这段代码是否优化并不影响执行结果,但是从代码的规范性以及可读性上面,最好是使用两个整形中间变量.二、由于ListBox1.Items.IndexOf操作量大,如果ListBox1没有进行排序,那么建议排序,如果不可以对其进行排序的,建立复制到TStringList当中并且加以排序。三、类似于sl.Strings[i],在下标(I值)以及内容没有改变的情况下,最好使用中间变量,否则这个访问也会偏移量计算带来的消耗。类似的还有Length,虽然也是直接根据偏移取出,但是得到偏移也是有计算量的。四、类似于str := str + ... 这样子的代码会造成str的不断复制,建立使用StringList等方式,临时存储,最后或者中间进行批量拼接。
      

  8.   

    for I :=strtoint(LabeledEdit1.Text) to StrToInt(LabeledEdit2.Text) do 
    StrToIntDef(LabeledEdit1.Text, 0);
      

  9.   


    procedure TForm4.btn3Click(Sender: TObject);
    var
      i: Integer;
      lstNo: TStringlist;
      sNo, pairNoStart, pairNoEnd: string;
      isNoDirty: Boolean;
      pair: Boolean;
      procedure AddNoSection;
      begin
        lstNo.Add(pairNoStart + '-' + pairNoEnd);
        pairNoStart := '';
        pairNoEnd := '';
      end;
    begin
      pair := False;
      lstNo:= TStringList.Create;
      try
        lstNo.BeginUpdate;
        try
          for I :=strtoint(edt1.Text) to StrToInt(edt2.Text) do begin
            sNo:= IntToStr(i);
            isNoDirty := lst1.Items.IndexOf(sNo) >= 0;
            if isNoDirty then begin
              if pairNoStart <> '' then begin
                AddNoSection;
                Continue;
              end;
            end;
            if pairNoStart ='' then
              pairNoStart := sNo;
            pairNoEnd := sNo;
          end;
          if pairNoStart <> '' then
          begin
            AddNoSection;
          end;
        finally
          lstNo.EndUpdate;
        end;
        edt3.Text := lstNo.DelimitedText;
      finally
        lstNo.Free;
      end;
    end;
    你先试试时间满足不满足你的需要.
      

  10.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        Edit3: TEdit;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        function GetAllNo(ABeginNo, AEndNo : Integer;AOutList :  TStrings) : String;
        function GetANo(ABegNo, AEndNo, AOutNo : Integer;var ALeft : array of integer) : Integer;
      end;var
      Form1: TForm1;implementation{$R *.dfm}function TForm1.GetAllNo(ABeginNo, AEndNo : Integer;AOutList :  TStrings) : String;
    var
      i, j, k, AOutNo, AOutCount : integer;
      AOut1, AOut2 : array of Integer;
      AOutTemp : array[0..3] of Integer;
    begin
      SetLength(AOut1, 2);
      AOut1[0] := ABeginNo;
      AOut1[1] := AEndNo;  for i := 0 to AOutList.Count - 1 do begin
        AOutNo := StrToInt(AOutList.Strings[i]);
        for j := 0 to (Length(AOut1) div 2) - 1 do begin
          AOutCount := GetANo(AOut1[j*2], AOut1[j*2+1], AOutNo, AOutTemp);      SetLength(AOut2, Length(AOut2) + AOutCount);
          for k := 0 to AOutCount - 1 do begin
            AOut2[Length(AOut2) - AOutCount + k] := AOutTemp[k];
          end;
        end;    SetLength(AOut1, Length(AOut2));
        AOut1 := AOut2;
        SetLength(AOut2, 0);
      end;  for i := 0 to (Length(AOut1) div 2) - 1 do begin
        Result := Result + IntToStr(AOut1[i*2]) + '-' + IntToStr(AOut1[i*2 + 1]) + ',';
      end;
    end;function TForm1.GetANo(ABegNo, AEndNo, AOutNo : Integer;var ALeft : array of integer) : Integer;
    var
      i : Integer;
    begin
      if (AOutNo = ABegNo) and (AOutNo = AEndNo) then begin
        Result := 0;
        exit;
      end;  if AOutNo = ABegNo then begin
        Result := 2;
        ALeft[0] := ABegNo + 1;
        ALeft[1] := AEndNo;
        exit;
      end;  if AOutNo = AEndNo then begin
        Result := 2;
        ALeft[0] := ABegNo;
        ALeft[1] := AEndNo - 1;
        exit;
      end;  if (AOutNo > ABegNo) and (AOutNo < AEndNo) then begin
        Result := 4;
        ALeft[0] := ABegNo;
        ALeft[1] := AOutNo - 1;
        ALeft[2] := AOutNo + 1;
        ALeft[3] := AEndNo;
      end else begin
        Result := 2;
        ALeft[0] := ABegNo;
        ALeft[1] := AEndNo;
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      a : TStringList;
    begin
      A := TStringList.Create;
      A.Add('2');
      A.Add('1000');
      A.Add('1005');
      A.Add('100009');
      Edit3.Text := GetAllNo(1000, 6000, A);
      A.Free;
    end;end.
      

  11.   

    简化如下:
    function Get1(AStart, AEnd: Integer; AExists: TStrings): string;  procedure AddResult(S, E: Integer);
      begin
        if S = E then
          Result := Result + Format('%d ', [S] )
        else
          Result := Result + Format('%d-%d ', [S, E]);
      end;var
      I, TS, TE: Integer;
    begin
      TS := AStart;
      TE := -1;
      for I := AStart to AEnd do
      begin
        if AExists.IndexOf(IntToStr(I)) > -1 then
        begin
          if TE <> -1 then
            AddResult(TS, I - 1);
          TS := I + 1;
          TE := -1;
        end else
          TE := I;
      end;
      if TE <> -1 then
        AddResult(TS, AEnd)
    end;
    优化如下:type
      PHash = ^THash;
      THash = record
        data: Cardinal;
        next: PHash;
      end;  PHashArr = ^THashArr;
      THashArr = array [0..0] of PHash;  PHashDataArr = ^THashDataArr;
      THashDataArr = record
        Size: Cardinal;
        List: PHashArr;
        Buffer: PHash;
      end;procedure InitHashList(var AHash: THashDataArr; AList: TStrings);
    var
      OldItem, NewItem: PHash;
      I, Count, KeyData: Integer;
    begin
      Count := AList.Count;
      AHash.Size := Count;
      AHash.List := AllocMem(Count * SizeOf(Pointer));
      AHash.Buffer := AllocMem(Count * SizeOf(THash));
      NewItem := AHash.Buffer;
      for I := 0 to AList.Count - 1 do
      begin
        KeyData := StrToIntDef(AList[I], -1);
        if KeyData = -1 then Continue;
        OldItem := AHash.List[KeyData mod Count];
        NewItem.next := OldItem;
        NewItem.data := KeyData;
        AHash.List[KeyData mod Count] := NewItem;
        Inc(NewItem);
      end;
    end;procedure UnInitHashList(var AHash: THashDataArr);
    begin
      FreeMem(AHash.Buffer);
      FreeMem(AHash.List);
      FillChar(AHash, SizeOf(AHash), 0);
    end;function IsExistsKey(var AHash: THashDataArr; AKey: Cardinal): Boolean;
    var
      Item: PHash;
    begin
      Item := AHash.List[AKey mod AHash.Size];
      while Assigned(Item) do
      begin
        Result := (Item.data = AKey);
        if Result then Exit;
        Item := Item.next;
      end;
      Result := False;
    end;function Get1(AStart, AEnd: Integer; AExists: TStrings): string;  procedure AddResult(S, E: Integer);
      begin
        if S = E then
          Result := Result + Format('%d ', [S] )
        else
          Result := Result + Format('%d-%d ', [S, E]);
      end;var
      I, TS, TE: Integer;
      hash: THashDataArr;
    begin
      InitHashList(hash, AExists);
      try
        TS := AStart;
        TE := -1;
        for I := AStart to AEnd do
        begin
          if IsExistsKey(Hash, I) then
          begin
            if TE <> -1 then
              AddResult(TS, I - 1);
            TS := I + 1;
            TE := -1;
          end else
            TE := I;
        end;
        if TE <> -1 then
          AddResult(TS, AEnd)
      finally
        UnInitHashList(hash);
      end;
    end;
      

  12.   

    调用:
    Edit1.Text := Get2(StrToInt(LabeledEdit1.Text), StrToInt(LabeledEdit2.Text), ListBox1.Items);
      

  13.   

    首先BigNo这个TStringList可以换成一个动态整型数组,这样比TStringList快一些
    另外StringGrid速度比较慢,可以换成TMSGrid(TMS系列控件)
    还有一个需要注意的是
      for i:=0 to sl.Count-1  do
        begin
             if trim(sl.Strings[i]) = '' then
            sl.Delete(i)这里最好换成for i := sl.Count - 1 downto 0 do
    因为按你那个循环,如果有行删除会造成数据的错误的
    比如第1行的数据删除了,原来第2行就变成第一行了,而你现在该操作的第2行的数据实际是原来第3行的数据
      

  14.   

    这个我试了,只要有这句I :=strtoint(edt1.Text)to StrToInt(edt2.Text)都很慢的,关键是号码的位数是不定的,上8位都有明显的延迟,我还仅仅是运行了这个循环,其他的全部注释掉了的,不过还是谢谢支持了
      

  15.   

    其实循环不算大,主要是lst1.Items.IndexOf(sNo)这句话里面有另外一个循环,所以导致了循环的大幅增加. 
      

  16.   

    比较函数
    function MyListCompare (List: TStringList; Index1, Index2: Integer): Integer;
    var
      I,J: Integer;
    begin
      I := Integer(List.Objects[Index1]) ;
      J := Integer(List.Objects[Index2]);
      if I = J then Result := 0
      else if I < J then Result := -1
      else Result := 1;
    end;示例处理代码:
    var
      InvalidNumList: TStringList;//废号码
      ValidNumList: TStringList;//有效号码(结果)  strStart,strEnd: AnsiString; //范围(即输入框的内容副本)
      iStart,iEnd: Integer;  iSecStart,iSecEnd: Integer; //分段
     
      iCurrent: Integer;  I: Integer;
    begin
      InvalidNumList := TStringList.Create;
      try
        ValidNumList := TStringList.Create;
        try      //添加作废号码
          //...InvalidNumList.Add(...)...
          InvalidNumList.Add('7');      InvalidNumList.Add('9');
          InvalidNumList.Add('10');      InvalidNumList.Add('14');
          InvalidNumList.Add('15');
          InvalidNumList.Add('16');      InvalidNumList.Add('21');      strStart := '1';
          strEnd := '20';      //转换成数值,以方便比较及运算
          for I := 0 to InvalidNumList.Count - 1 do begin
            InvalidNumList.Objects[I] := TObject(StrToIntDef(InvalidNumList[I], 0));
          end;
          //作废号码排序
          InvalidNumList.CustomSort(MyListCompare);      //输入范围处理
          iStart := StrToIntDef(strStart, 0);
          iEnd := strToIntDef(strEnd, 0);      Assert(iStart < iEnd);//检查输入有效性      iSecStart := iStart;      for I := 0 to InvalidNumList.Count - 1 do begin
            iCurrent := Integer(InvalidNumList.Objects[I]);        if iCurrent > iEnd then iSecEnd := iEnd
            else  iSecEnd := iCurrent - 1;        if iSecEnd <= iSecStart then begin
              iSecStart := iCurrent + 1;
              continue;
            end;        ValidNumList.Add(IntToStr(iSecStart) + '-' + IntToStr(iSecEnd));
            iSecStart := iCurrent + 1;        if iCurrent > iEnd then break;      end;      //显示结果
          ShowMessage(ValidNumList.Text);
        finally
          ValidNumList.Free;
        end;  finally
        InvalidNumList.Free;
      end;
    end;
      

  17.   

    没仔细看,不知道程序啥功能。"out of memory"  内存不够用了,这个好象要循环次数没啥关系,跟线程也没啥关系如果有很多数据,用数据库倒是可以考虑。