我有如下的文本文件:
No      year    Width
4 1961 119
4 1962 128
4 1963 41
4 1964 75
4 1965 214
4 1966 23
4 1967 103
4 1968 171
4 1969 55
4 1970 25
5 1961 89
5 1962 170
5 1963 24
5 1964 25
5 1965 122
5 1966 6
5 1967 185
5 1968 105
5 1969 93
5 1970 95
5 1971 85
....
....
....
(共4000行)
注意:各个No的年份数有可能不一样。
现在我想把这种格式的文本转换成:
Year   4   5  6 ... 
1961   119 89
1962   128 170
1963   41  24
1964
1965
1966
1967
1968
1969
1970
...
...
该如何设计代码呢?
好像这类问题很典型一样

解决方案 »

  1.   

    用链表,表示年份以及本年份No的链表头,No链表存储本年份的全部No
    在读文件是构建,显示时按年份遍历即可
    如果要排序,在构件时完成
      

  2.   


    procedure TForm1.Button1Click(Sender: TObject);
    var
      sFile,sYears,sLine: TStringList;
      i,iIndex: Integer;
      sYear,sNoNew,sNo: String;
    begin
      sNoNew := '';
      sFile := TStringList.Create;
      sYears := TStringList.Create;
      sLine := TStringList.Create;
      sFile.LoadFromFile('c:\1.txt');
      Application.ProcessMessages;
      try
        for i := 1 to sFile.Count - 1 do begin
          sLine.CommaText := sFile.Strings[i];
          sYear := sLine.Strings[1];
          if sYears.IndexOf(sYear) < 0 then sYears.Add(sYear);
        end;
        Memo2.Clear;
        Memo2.Lines.Add('Year');
        Memo2.Lines.AddStrings(sYears);
        for i := 1 to sFile.Count - 1 do begin
          sLine.CommaText := sFile.Strings[i];
          sNo := sLine.Strings[0];
          sYear := sLine.Strings[1];
          iIndex := sYears.IndexOf(sYear) + 1;
          if sNo <> sNoNew then begin
            Memo2.Lines[0] := Memo2.Lines[0] + ' ' + sNo;
            sNoNew := sNo;
          end;
          Memo2.Lines[iIndex] := Memo2.Lines[iIndex] + ' ' + sLine.Strings[2];
        end;
        Memo2.Lines.SaveToFile('c:\2.txt');
      finally
        sFile.Free;
        sYears.Free;
        sLine.Free;
      end;
    end;
      

  3.   

    我又仔细查询了代码,发现,就是出现年份这个数据项上。
    因为,有的年份是从1961-2007,有的是从1971-2007,
    而:
      if sNo <> sNoNew then begin
            Memo2.Lines[0] := Memo2.Lines[0] + ' ' + sNo;
            sNoNew := sNo;
          end;
          Memo2.Lines[iIndex] := Memo2.Lines[iIndex] + ' ' + sLine.Strings[2];
    就会把原本是空的记录(比如1961-1970没有数据),用下一个记录的数值来填充,
    而我的目的是想用一个特殊的标志符(比如#)来表示空的数据。望共同探讨,如何解决。已经很接近处理要求了。再次谢谢!◎
      

  4.   

    用制表符分割不就清楚了,而且还可以用EXCEL强制打开观察
      

  5.   

    不是那样的,在Excel里我知道如何处理,我现在是想讨论程序代码的问题。
      

  6.   


    procedure TForm1.AddBlanks;
    var
      i: Integer;
    begin
      for i := 1 to Memo2.Lines.Count - 1 do
        Memo2.Lines[i] := Memo2.Lines[i] + #9'#';
    end;procedure TForm1.AddData(const AIndex: Integer; const AData: String);
    var
      s: String;
    begin
      s := Memo2.Lines[AIndex];
      Memo2.Lines[AIndex] := Copy(s,1,Length(s) - 1) + AData;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      sFile,sYears,sLine: TStringList;
      i,iIndex: Integer;
      sYear,sNoNew,sNo: String;
    begin
      sNoNew := '';
      sFile := TStringList.Create;
      sYears := TStringList.Create;
      sLine := TStringList.Create;
      sFile.LoadFromFile('c:\1.txt');
      Application.ProcessMessages;
      Memo2.Lines.BeginUpdate;
      try
        for i := 1 to sFile.Count - 1 do begin
          sLine.CommaText := sFile.Strings[i];
          sYear := sLine.Strings[1];
          if sYears.IndexOf(sYear) < 0 then sYears.Add(sYear);
        end;
        Memo2.Clear;
        Memo2.Lines.Add('Year');
        Memo2.Lines.AddStrings(sYears);
        for i := 1 to sFile.Count - 1 do begin
          sLine.CommaText := sFile.Strings[i];
          sNo := sLine.Strings[0];
          sYear := sLine.Strings[1];
          iIndex := sYears.IndexOf(sYear) + 1;
          if sNo <> sNoNew then begin
            Memo2.Lines[0] := Memo2.Lines[0] + #9 + sNo;
            AddBlanks;
            sNoNew := sNo;
          end;
          AddData(iIndex,sLine.Strings[2]);
        end;
        Memo2.Lines.SaveToFile('c:\2.txt');
        Memo2.Lines.EndUpdate;
      finally
        sFile.Free;
        sYears.Free;
        sLine.Free;
      end;
    end;