Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Посоветуйте класс похожий на TStringList


Автор: Ibragim 26.12.2006, 02:30
Добрый вечер.
Насоветуйте, может не стоит изобретать велосипед - может уже есть такое.

Нужен класс, с функционалом TStringList, а именно
- быстрая и удобная загрузка/сохранение в файл
- быстая сортировка, уже реализована
- если список сортирован, то Add добавляет в соответствующее место а не в конец списка.
- удобный вывод, например в TStringGrid  (MyStringGrid.Strings[0] := MyStringList;)

Мне же нужно такое же, только для ПАР строк. Чтобы не писать самому сортировки по столбцу 1 и 2, загрузка-сохранение в цикле и т.п.

Кто знает (если такое есть) - подскажите плз.

Автор: Fedia 26.12.2006, 06:18
Три варианта:
1. Строки в TStringList заносить с разделителем типа: 'поле1|поле2' (не удобен для сортировки по второму полю).
2. Использовать два объекта TStringList. При сохранении строки второго стринглиста добавлять в первому.
3. Написать наследника от класса  TStringList (отношение типа "иметь").
ЗЫ: готовое решение едва ли удастся найти.

Автор: Akella 26.12.2006, 08:43
у TStringList это реализовано, смотри свойства Names и Values
стандартный разделитель, помоему, знак равно (=)

Код

procedure TForm4.Button1Click(Sender: TObject);
Var
 s:TStringList;
 Name, Val: string;
 i:integer;
begin
 s:=TStringList.Create;
 try
     s.LoadFromFile('c:\11.txt');
     {
     #формат файла:
     поле=значение
     поле=значение
     поле=значение
     поле=значение
     поле=значение
     поле=значение
     }
     For i:= 0 to s.Count-1 do
       ShowMessage('Название поля: '+s.Names[i]+#13#10+ 'значение: '+s.Values[i]);
 finally
   FreeAndNil(s);
 end;

end;


Автор: Teran 26.12.2006, 10:02
Цитата(Fedia @  26.12.2006,  06:18 Найти цитируемый пост)
ЗЫ: готовое решение едва ли удастся найти.

record + TList = готовое решение

Автор: Mephisto 26.12.2006, 10:49
Цитата(Ibragim @  26.12.2006,  03:30 Найти цитируемый пост)
если список сортирован, то Add добавляет в соответствующее место а не в конец списка.

А чем insert не подходит?
Цитата(Akella @  26.12.2006,  09:43 Найти цитируемый пост)
стандартный разделитель, помоему, знак равно (=)

Можно установить через Delimiter.
Ibragim, думается твой вариант.  smile 

Автор: Ibragim 26.12.2006, 12:36
Гуд, спасибо за советы, будем попробовать что ближе к сердцу ляжет. 
Похоже, проще всего Names и Values и TStringList. Но поэксперементируем

Автор: MetalFan 26.12.2006, 13:38
а мне кажется самое оптимальное - это наследник от TList с необходимым функционалом... естесьно самописный

Автор: aktuba 26.12.2006, 14:35
Полностью поддерживаю Metalfan-а. Это самый правильный путь, да и если в будущем понадобится улучшения - TList просто необходим.

Автор: Ibragim 26.12.2006, 15:36
Цитата(MetalFan @  26.12.2006,  13:38 Найти цитируемый пост)
TList с необходимым функционалом


Не факт что TList. Вполне возможно TStringList. Тогда дописать только обращение к первой-второй части строки, и все. Хотя остаются проблемы с выводом....

PS 

Akella, s.Values[i] работать не будет. Там в квадратных скобках имя надо писать. Поэтому в несортированых списках тормозиииить должно немерянно. Хотя сам не пробовал.

В общем, всем спасибо за отзывы, будем работать smile 

Автор: Akella 26.12.2006, 16:52
Цитата(Ibragim @  26.12.2006,  15:36 Найти цитируемый пост)
Akella, s.Values[i] работать не будет. Там в квадратных скобках имя надо писать.

а как на счёт
Код

s.ValueFromIndex[i];


Автор: aktuba 26.12.2006, 17:11
Ibragim - не только с выводом, но и с сортировкой по столбцам. Лучше все-таки TList.

Автор: MetalFan 26.12.2006, 17:12
накидал тут за 20 минут для обчего развития примитивный примерчик
Код

interface

uses
   classes, contnrs;

type

  TRowList = class;

  TRowItem = class
  private
    FStringList: TStringList;
    FParent: TRowList;
    function GetColCount: Integer;
    procedure SetColCount(const Value: Integer);
    function GetCol(AIndex: Integer): string;
    procedure SetCol(AIndex: Integer; const Value: string);
  protected
    property ColCount: Integer read GetColCount write SetColCount;
  public
    constructor Create( AParentList: TRowList; AColCount: Integer );
    destructor Destroy; override;
    property Col[ AIndex: Integer ]: string read GetCol write SetCol;
    function AsText( ADelimiter: Char = ',' ): string;
  end;

  TRowList = class
  private
    FList: TObjectList;
    FColCount: Integer;
    function GetCell(ACol, ARow: Integer): string;
    function GetRow(AIndex: Integer): TRowItem;
    procedure SetCell(ACol, ARow: Integer; const Value: string);
    function GetColCount: Integer;
    procedure SetColCount(const Value: Integer);
    function GetRowCount: Integer;
    procedure SetRowCount(const Value: Integer);
  public
    constructor Create;
    destructor Destroy; override;
    function AddRow( ARow: TRowItem ): Integer; overload;
    function AddRow(): TRowItem; overload;
    property Rows[ AIndex: Integer]: TRowItem read GetRow;
    property RowCount: Integer read GetRowCount write SetRowCount;
    property ColCount: Integer read GetColCount write SetColCount;
    property Cell[ ACol, ARow: Integer]: string read GetCell write SetCell;
    function AsText( AColDelim: Char = ','; const ARowDelim: string = sLineBreak): string;
  end;

implementation

{ TRowItem }

function TRowItem.AsText(ADelimiter: Char): string;
begin
  FStringList.Delimiter := ADelimiter;
  Result := FStringList.DelimitedText;
end;

constructor TRowItem.Create( AParentList: TRowList; AColCount: Integer );
begin
  FStringList := TStringList.Create;
  ColCount := AColCount;
end;

destructor TRowItem.Destroy;
begin
  FStringList.Free;
  inherited;
end;

function TRowItem.GetCol(AIndex: Integer): string;
begin
  Result := '';
  if (AIndex >=0) and (AIndex < ColCount) then
    Result := FStringList[AIndex];
end;

function TRowItem.GetColCount: Integer;
begin
  Result := FStringList.Count;
end;

procedure TRowItem.SetCol(AIndex: Integer; const Value: string);
begin
  if (AIndex <0) or (AIndex >= ColCount) then Exit;
  FStringList[AIndex] := Value;
end;

procedure TRowItem.SetColCount(const Value: Integer);
begin
  if Value < 0 then Exit;
  if Value > FStringList.Count then
    while Value > FStringList.Count do
      FStringList.Add('')
  else
  if Value < FStringList.Count then
   while Value < FStringList.Count do
     FStringList.Delete(FStringList.Count-1)
end;

{ TRowList }

function TRowList.AddRow: TRowItem;
var
  lRow: TRowItem;
begin
  Result := nil;
  lRow := TRowItem.Create( Self, FColCount );
  if AddRow( lRow ) <> -1 then
    Result := lRow;
end;

function TRowList.AddRow(ARow: TRowItem): Integer;
begin
  Result := FList.Add( ARow )
end;

constructor TRowList.Create;
begin
  FList := TObjectList.Create( True );
end;

destructor TRowList.Destroy;
begin
  FList.Free;
  inherited;
end;

function TRowList.AsText(AColDelim: Char;
  const ARowDelim: string): string;
var
  i: Integer;
begin
  Result := '';
  for i := 0 to pred( RowCount ) do
    Result := Result + Rows[i].AsText( AColDelim ) + ARowDelim;
end;

function TRowList.GetCell(ACol, ARow: Integer): string;
begin
  Result := Rows[ARow].Col[ACol];
end;

function TRowList.GetColCount: Integer;
begin
  Result := FColCount;
end;



function TRowList.GetRow(AIndex: Integer): TRowItem;
begin
  Result := TRowItem( FList[AIndex] );
end;

function TRowList.GetRowCount: Integer;
begin
  result := FList.Count;
end;

procedure TRowList.SetCell(ACol, ARow: Integer; const Value: string);
begin
  Rows[ARow].Col[ACol] := Value;
end;

procedure TRowList.SetColCount(const Value: Integer);
var
  i: Integer;
begin
  if FColCount = Value then exit;
  for i := 0 to pred( RowCount ) do
    Rows[i].ColCount := Value;
  FColCount := Value;
end;

procedure TRowList.SetRowCount(const Value: Integer);
begin
  if Value < 0 then Exit;
  if RowCount < Value then
    while RowCount < Value do
      AddRow
  else
  if RowCount > Value then
    while RowCount > Value do
      FList.Delete( RowCount-1 );
end;


сортировку сам прикрутишь, я думаю)

пример использования:
Код

var
  i, j: Integer;
  lRCount, lCCount: Integer;
  lRowList: TRowList;
  lText: string;
  lRect: TRect;  
begin
  Randomize;
  lRCount := Random( 10 )+5;
  lCCount := Random( 10 )+5;
  lRowList := TRowList.Create;
  try
    lRowList.ColCount := lCCount;
    lRowList.RowCount := lRCount;
    for i := 0 to pred( lRCount ) do
      for j := 0 to pred( lCCount ) do
        lRowList.Cell[j, i] := IntToStr( Random(100));
    lText := lRowList.AsText('*');
    lRect := Self.ClientRect;
//    OffsetRect( lRect, 10, 150 );
    Self.Canvas.FillRect(lRect);
    DrawText( Self.Canvas.Handle, PChar(lText), length( lText), lRect, DT_LEFT or DT_NOCLIP)
  finally
    lRowList.Free;
  end;

end;


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)