问题如下:
   我有个数组共10000项,类型是string,现在我的问题是,咋样找出其中相同的项,而且要得到相同项出现的次数,焦点问题:我也可以得到,就是算法不太好,特别慢!请大家帮忙了,谢谢!

解决方案 »

  1.   

    var
     i, j: integer;
     ArrStr: Array [0..10000] of string;
    begin
      j:=0;
      for i:=0 to 10000-1 do
      begin
        也只有这种笨方法了,嘿嘿,本想写,但是发觉也很没效率,就不写了
      end;
    end;
      

  2.   

    -----------排序开始-------------------------------------------------}
    procedure TForm_Report.sort_result;
    var i,j:integer;
        m_m:computername;
    begin
      for j:=0 to k_k_k-1 do
      for i:=0 to k_k_k-j do
      begin
        if outcome[i].Index<outcome[i+1].Index  then
        begin
           m_m:=outcome[i];
           outcome[i]:=outcome[i+1];
           outcome[i+1]:=m_m;
        end;
      end;
    end;
    {-----------排序结束-------------------------------------------------}
      

  3.   

    type ComputerName= record
       Name:string; //存放名称
       Index:integer;//对应个数
    end;
      private
        stat_value:string;
        my_listview:array of string;//控制结果名称和出现次数
       item_count:integer; //控制结果个数
       outcome:array of ComputerName;
       k_k_k:integer;//主机名的个数
      public
    {-----------合并相同项和统计其个数开始-------------------------------}
    procedure TForm_Report.stat_result;
    var i:integer;
        t_t:boolean;
        j:integer;
    begin
      for i:=0 to item_count-1 do
        begin
          t_t:=false;
          for j:=0 to item_count-1 do
          begin
            if ComPareText(my_listview[i],outcome[j].Name)=0 then
            begin
              t_t:=true;
              inc(outcome[j].Index);
              break;
            end ;
          end;
          if not t_t then
          begin
            outcome[k_k_k].name:=my_listview[i];
            inc(outcome[k_k_k].Index); //标识出现个数
            k_k_k:=k_k_k+1;//主机名的个数
          end;
         end;
    end;
    {-----------合并相同项和统计其个数结束-------------------------------}
      

  4.   

    算法一,可能就是你那种:type
      TSortTable = class
      public
        Value: string;
        Count: Integer;
      end;procedure TForm1.Button1Click(Sender: TObject);
    var
      tls               : Tstrings;
      dls               : TStrings;
      i, b              : Integer;
      st                : TSortTable;
      d                 : dword;
    begin
      d := GetTickCount;
      memo1.lines.Clear;
      tls := tstringList.create;
      dls := tstringList.create;
      for i := 0 to 10000 do
        tls.Add(inttostr(Random(i)));  for i := tls.Count - 1 downto 0 do
      begin
        if dls.IndexOf(tls.Strings[i]) = -1 then
        begin
          st := TSortTable.Create;
          st.Value := tls.Strings[i];
          st.Count := 1;
          dls.AddObject(tls.Strings[i], st);
        end
        else
          TSortTable(dls.Objects[dls.IndexOf(tls.Strings[i])]).Count :=
          TSortTable(dls.Objects[dls.IndexOf(tls.Strings[i])]).Count + 1;
        tls.Delete(i);
      end;
      d := GetTickCount - d;
      Label1.caption := 'Time:' + Inttostr(d);  for i := 0 to dls.Count - 1 do
      begin
        dls.Strings[i] := TSortTable(dls.Objects[i]).Value +
          '|' + inttostr(TSortTable(dls.Objects[i]).Count);
        TSortTable(dls.Objects[i]).free;
      end;  Memo1.Lines.Assign(dls);
      tls.Free;
      dls.free;
    end;总对10000个字符串统计,花了34秒;改进一下,先排序,然后再统计,13秒procedure TForm1.Button2Click(Sender: TObject);
    var
      tls               : Tstrings;
      i                 : integer;
    begin
      listbox1.items.clear;
      listbox1.items.beginUpdate;
      tls := tstringList.create;
      for i := 0 to 10000 do
        tls.Add(inttostr(Random(i)));
      listbox1.Items.Assign(tls);
      tls.free;  listbox1.Sorted := true;
      listbox1.items.endUpdate;
    end;procedure TForm1.Button3Click(Sender: TObject);
    var
      i                 : Integer;
      st                : TSortTable;
      id                : string;
      d                 : dword;
    begin
      d := GetTickCount;
      listbox2.items.clear;
      listbox2.items.beginUpdate;
      for i := listbox1.Items.Count - 1 downto 0 do
      begin
        id := listbox1.Items.Strings[i];
        if listbox2.Items.IndexOf(id) = -1 then
        begin
          st := tSortTable.Create;
          st.Value := id;
          st.Count := 1;
          listbox2.Items.AddObject(id, st);
        end
        else
          TSortTable(listbox2.Items.Objects[listbox2.items.IndexOf(id)]).Count :=
          TSortTable(listbox2.Items.Objects[listbox2.items.IndexOf(id)]).Count + 1;
      end;  for i := 0 to listbox2.Items.Count - 1 do
      begin
        Listbox2.Items.Strings[i] := TSortTable(Listbox2.Items.Objects[i]).Value +
          '|' + inttostr(TSortTable(Listbox2.Items.Objects[i]).Count);
        TSortTable(Listbox2.Items.Objects[i]).free;
      end;
      listbox2.Sorted:=true;
      listbox2.items.endupdate;
      d := GetTickCount - d;
      Label2.caption := 'Time:' + Inttostr(d);
    end;组件用到
        Button1: TButton;
        Memo1: TMemo;
        Label1: TLabel;
        ListBox1: TListBox;
        Button2: TButton;
        ListBox2: TListBox;
        Label2: TLabel;
        Button3: TButton;
      

  5.   

    排序后找有个好处就是遍历一次即可了,我的第二个算法就是直接排序后找,增加到目的列中用了IndexOf ,这个有个坏处就是数据多了后就会影响速度,排序过的源列表,如果(Index-1)<>(Index+1) 的话,目的的列可以直接add,而不是IndexOf ,这个是需要优化的地方,速度会更快
      

  6.   

    改进的算法二,先排序,再统计;1.4秒:procedure TForm1.Button2Click(Sender: TObject);
    var
      tls               : Tstrings;
      i                 : integer;
    begin
      listbox1.items.clear;
      listbox1.items.beginUpdate;
      tls := tstringList.create;
      for i := 0 to 10000 do
        tls.Add(inttostr(Random(i)));
      listbox1.Items.Assign(tls);
      tls.free;  listbox1.Sorted := true;
      listbox1.items.endUpdate;
    end;procedure TForm1.Button3Click(Sender: TObject);
    var
      i, c, n           : Integer;
      Tls:TStrings;
      st                : TSortTable;
      id                : string;
      b                 : string;
      d                 : dword;
    begin
      d := GetTickCount;
      Tls := Tstringlist.Create;
      Tls.Assign(Listbox1.Items);
      listbox2.items.clear;
      listbox2.items.beginUpdate;
      b := ''; //对比项目
      n := 0; //索引位置
      c := 0; //记数  for i := 0 to Tls.Count - 1 do
      begin
        id := Tls.Strings[i];
        if id = b then  //对比旧数据
          c := c + 1; //如果相同则记数加一
        if id <> b then //如果不相同则建立新的统计列
        begin
          Inc(N,1); //增加索引位置
          st := tSortTable.Create;
          st.Value := id;
          st.Count := 1; //初始记数1
          listbox2.Items.AddObject(id, st);
          if c > 1 then
            TSortTable(Listbox2.Items.Objects[n - 2]).Count := c; //修改上一列的总数
          c := 1;
          b := id;
        end;
      end;
      TSortTable(ListBox2.Items.Objects[n-1]).count :=c; //修改最后列总数
      Tls.Free;  for i := 0 to listbox2.Items.Count - 1 do
      begin  //这里是列出项目,并加上数量
        Listbox2.Items.Strings[i] := TSortTable(Listbox2.Items.Objects[i]).Value +
          '|' + inttostr(TSortTable(Listbox2.Items.Objects[i]).Count);
        TSortTable(Listbox2.Items.Objects[i]).free;
      end;
      listbox2.Sorted := true;
      listbox2.items.endupdate;
      d := GetTickCount - d;
      Label2.caption := 'Time:' + Inttostr(d);
    end;
    排序+一次遍历
      

  7.   

    10万笔数据排序时间花了460秒,还可以优化,优化的方法如下
    避免过多的内存拷贝,不使用Tstrings或者是listbox 这些额外的开销,直接用数组进行处理。
      

  8.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ComCtrls, DB, ADODB;type
      TForm1 = class(TForm)
        Button1: TButton;
        ADOTable1: TADOTable;
        Button2: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
        sl: TStringList;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var
      i: Integer;
    begin
      Randomize;
      sl.Clear;
      for i := 1 to 10000 do
        sl.Add(IntToStr(random(10001)));
      Application.MessageBox('Finished.', 'hint', MB_ICONINFORMATION);
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      sl := TStringList.Create;
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      sl.Free;
    end;procedure TForm1.Button2Click(Sender: TObject);
    var
      dblBeginTime, dblEndTime: TTime;
      iCount, i: Integer;
      sTemp: String;
      slTemp: TStringList;
    begin
      sTemp := '';
      iCount := 0;  slTemp := TStringList.Create;
      try
        dblBeginTime := Time;
        sl.Sort;
        for i := (10000 - 1) downto 0 do
          if (sTemp <> sl.Strings[i]) then
          begin
            if ((i + 1) < 10000) then slTemp.Add(sTemp + ':' + IntToStr(iCount));        sTemp := sl.Strings[i];
            iCount := 1;
          end
          else
            Inc(iCount);
        slTemp.Add(sTemp + ':' + IntToStr(iCount));
        dblEndTime := Time;
        Application.MessageBox(PChar('Time Used:'#13#10 +
          TimeToStr(dblEndTime - dblBeginTime)), 'Hint', MB_ICONINFORMATION);
        //毫秒级的时间,呵呵,(dblEndTime - dblBeginTime)的Double值是 1.2E-6 左右    Memo1.Lines.Assign(slTemp);
      finally
        slTemp.Free;
      end;
    end;end.
      

  9.   

    但是像楼主的“数组共10000项,类型是string”,那可能比较多的时间是消耗在字符串的比较上面(因为我跟萧寒的方法好像都是随机生成的数字而已,很短的字符串)