Аналог TStringList для записей

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

krab
постоялец
Сообщения: 108
Зарегистрирован: 17.02.2010 17:23:08

Аналог TStringList для записей

Сообщение krab »

Как лучше хранить набор записей? Нужен аналог StringList. Есть ли что-то с простым (ведущим к минимуму ошибок) интерфейсом, без ручной работы с указателями и т. п.?
То есть:

Код: Выделить всё

type
   TPerson = record
       Name, Telephone, Address : String;     
   end;

var
  Many_Persons : TRecordList;
  x, y : TPerson;

begin
  Many_Persons := TRecordList.Create(TPerson);

  x.Name := 'Holmes';
  x.Telephone := '1234567890';
  x.Address := '221b Baker Street London '

  Many_Persons.Add(x);

  y := Many_Persons[0];
end
А.Н.
постоялец
Сообщения: 230
Зарегистрирован: 13.03.2010 11:23:58

Сообщение А.Н. »

TObjectList или TCollection?
Аватара пользователя
hinst
энтузиаст
Сообщения: 781
Зарегистрирован: 12.04.2008 18:32:38

Сообщение hinst »

шаблонный список. скачайте мой! viewtopic.php?f=41&t=5898
или в фпц тоже вот ещё есть TGList вроде...
А.Н.
постоялец
Сообщения: 230
Зарегистрирован: 13.03.2010 11:23:58

Сообщение А.Н. »

А коллекция чем плоха?
krab
постоялец
Сообщения: 108
Зарегистрирован: 17.02.2010 17:23:08

Сообщение krab »

А.Н. писал(а):А коллекция чем плоха?

Код: Выделить всё

type
   // Forward declarations
   TMyCollectionItem=class;
   TMyCollection=class;


   TMyCollection=class(TCollection)
   private
      function GetItem(Index: Integer): TMyCollectionItem;
      procedure SetItem(Index: Integer; const Value: TMyCollectionItem);
   public
      Constructor Create;
      property Items[Index: Integer]: TMyCollectionItem read GetItem write SetItem; default;
   end;

   TMyCollectionItem=class(TCollectionItem)
   private
      FString:String;
      FBool: Boolean;
      FInt:integer;
      FObj:TSomeClass;
      Procedure SetObj(const Value: TSomeClass);
   public
      procedure Assign(Source:TPersistent);override;
      constructor Create(AOwner:TCollection);override;
      destructor destroy;override;
   published
      property BoolProp:Boolean read FBool write FBool;
      property StringProp:String read FString write FString;
      property IntProp:integer read FInt write FInt;
      property ObjProp: TSomeClass read FObj write SetObj;
   end;

{ TMyCollection }

constructor TMyCollection.Create;
begin
  inherited Create(TMyCollectionItem);
end;

function TMyCollection.GetItem(Index: Integer): TMyCollectionItem;
begin
  Result:=TMyCollectionItem(inherited GetItem(Index));
end;

procedure TMyCollection.SetItem(Index: Integer; const Value: TMyCollectionItem);
begin
  inherited SetItem(index,value);
end;

{ TMyCollectionItem }

procedure TMyCollectionItem.Assign(Source: TPersistent);
begin
  if Source is TMyCollectionItem then
     with Source as TMyCollectionItem do
  begin
     FString:=StringProp;
     FBool:=BoolProp;
     FInt:;=Intprop
         FObj.Assign(ObjProp);
  end
  else
     inherited Assign(source);
end;

constructor TMyCollectionItem.Create(AOwner: TCollection);
begin
  inherited Create(AOwner);
  FObj:=TSomeClass.Create(self);
end;

destructor TMyCollectionItem.destroy;
begin
  inherited;
  FObj.Free;
end;

procedure TMyCollectionItem. SetObj(const Value: TSomeClass);
begin
  FEntries.Assign(Value);
end;

И все это ради того, чтобы получить аналог:

Код: Выделить всё

struct TItem {
      std::string FString;
      bool Boolean;
      int integer;
      myobj SomeClass;
}
std::list<TItem> many;


Добавлено спустя 3 минуты 2 секунды:
У меня много разных записей, поэтому строки, что я привел для TCollection, можно смело умножать на 10... :shock:
Аватара пользователя
alexs
долгожитель
Сообщения: 4066
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

krab писал(а):У меня много разных записей, поэтому строки, что я привел для TCollection, можно смело умножать на 10...

Вместо записи используем класс, и TList. Ничего объявлять дополнительно не надо. Заодно данные правильно будут оформленны. И проверки внутри объекта на допустимость данных размещать более правильно. А вот устройство хранения данных не обязанно знать, какие данные коректны для твоей записи.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

/offtopic
hinst
а у шаблонов как со стабильностью и отладкой? у меня давно напрашивается шаблонизация, но както ссыкотно
А.Н.
постоялец
Сообщения: 230
Зарегистрирован: 13.03.2010 11:23:58

Сообщение А.Н. »

krab писал(а):У меня много разных записей, поэтому строки, что я привел для TCollection, можно смело умножать на 10...

От TCollection наследовать, в общем-то, необязательно.
Только, как вы собираетесь делать Assign, используя какой-то там список? Т.е. запись должна быть не с public, а с published свойствами, и потребуется использовать RTTI? Тоже, при желании, возможно реализовать и для коллекции. Затем, использовать один потомок.
Только имеет ли смысл? Может, тогда, лучше сделать метод Assign в записи или, вообще, правильнее объекты использовать? Коллекция сама вызовет их Assign.

А так, достаточно переопределить только TCollectionItem. Что вы хотите не понимаю. Если у вас много типов записей, будет такое же число, только они станут потомками элемента коллекции.

Аналогичная ситуация с шаблонами. Всё-равно, вам придётся определять списки для всех типов. Если же вам не нужна проверка типов, вы можете использовать TObjectList. В чём проблема? Нужно изобрести велосипед?
Аватара пользователя
hinst
энтузиаст
Сообщения: 781
Зарегистрирован: 12.04.2008 18:32:38

Сообщение hinst »

@zub
ну я использовал шаблоны в нескольких своих проектах. вроде нормально. при исключении выдаётся и номер строки, и имя метода, и имя шаблона, и тип, по которому он специализируется, так что с отладкой вроде-бы нормально. некоторые хитрые конструкции пока не собираются или не линкуются, а так, обычные во время выполнения работают нормально. глюков не замечал.
@krab
ну вот шаблоны в таком случае для вас единственный вариант.
быстро,
просто,
не нужно много писать,
не нужно приводить типы,
аналогия с C++
остаётся только выбрать, какие использовать

P.S.: Под хитрыми конструкциями понимал наследование шаблонов. надеюсь, в будущих версиях FPC оно появится
Аватара пользователя
alexs
долгожитель
Сообщения: 4066
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

hinst писал(а):аналогия с C++

Это главное? :D
А.Н.
постоялец
Сообщения: 230
Зарегистрирован: 13.03.2010 11:23:58

Сообщение А.Н. »

@krab
ну вот шаблоны в таком случае для вас единственный вариант.
быстро,
просто,
не нужно много писать,
не нужно приводить типы,
аналогия с C++
остаётся только выбрать, какие использовать

"Быстро, качественно, недорого. Выберите любые два пункта."? ;)
Единственное, что плохо с коллекцией, - приведение типов. Много писать, в принципе, тоже не нужно.
Причём, также быстро и просто. Аналогия с C++ меня почему-то настораживает. :lol:
yurgel
новенький
Сообщения: 37
Зарегистрирован: 29.06.2010 16:06:58

Сообщение yurgel »

krab писал(а):И все это ради того, чтобы получить аналог:

Код: Выделить всё

struct TItem {
      std::string FString;
      bool Boolean;
      int integer;
      myobj SomeClass;
}
std::list<TItem> many;


можно ещё короче: Records: array of array of Variant. чтобы не было путаницы, индексы первого массива выносите в константы, и тогда

Код: Выделить всё

  Name := Records [IDX_NAME, 20];


- это обращение к полю IDX_NAME в двадцатой (а точнее - в двадцать первой, т.к. у динамических массивов индексация идёт с нуля) строке aka записи.
krab
постоялец
Сообщения: 108
Зарегистрирован: 17.02.2010 17:23:08

Сообщение krab »

Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Сообщение VirtUX »

Есть массив параметров типа record. Есть список строковых идентификаторов для этого массива параметров. Сейчас это выглядит в двух вариантах:
Первый:

Код: Выделить всё

PNodeString = ^NodeString;
NodeString = record
Next, Pred: PNodeString;
sID: string;
p: Pointer;
end;

Второй:

Код: Выделить всё

ArrNode = array of record
  sID: string;
  p: Pointer;
end;

В p: Pointer хранятся адреса на параметры в виде записей:

Код: Выделить всё

AnyParam = record
p1: AnyType;
...
pN: AnyType;
end;

где AnyType - это любой возможный тип данных.
Для первого варианта у меня уже написаны процедуры сортировки, поиска и т.п. по sID. Для второго все, что мне нужно есть в TStringList, но он не может хранить простые Pointer, а лишь обязательно TObject. Создавать целые объекты для миллионов параметров AnyParam мне кажется ресурсозатратным для ОЗУ.
Все параметры уникальны и не повторяются. Т.е. объектные методы типа Assign мне не нужны. Да и вообще никакие объектные методы мне, применительно к параметрам, не нужны!
Где бы взять такой TStringList, имеющий возможность хранить просто Pointer вместо TObject? Или как обмануть TStringList?
svk12
постоялец
Сообщения: 411
Зарегистрирован: 09.06.2008 18:42:47

Сообщение svk12 »

Например:

Код: Выделить всё

type
TPointerStore =class
FPointer:Pointer;
end;


И вставляйте его в TStringList.
Ответить