Я даже не хочу представить медлительность этого решения.

аю, что все, кто когда-либо использовал Delphi VirtualStringTree, согласятся, что это отличный элемент управления. Это «виртуальный» элемент управления (ваши данные должны храниться где-то еще), поэтому я подумал, какая структура данных лучше всего подходит для такой задачи? ИМО, что структура данных должна поддерживать иерархию, она должна быть быстрой и легко расширяемой. Самой простой реализацией было бы использование записи, и это то, что предлагает большая часть документации, которую можно найти. Но что, если вам нужно сделать быстрый поиск, подсчитать итоги и т. Д.? Какую структуру данных вы используете вместе с VirtualStringTree?

EDIT1Я использую Delphi 2010

Хорошо, я постараюсь рассказать подробнее о моих требованиях. Размер данных может быть очень переменным, от 1 до тысяч элементов. Каждый элемент может содержать несколько строк, целочисленных значений. Мне нужен произвольный доступ, мои данные могут меняться много раз за время существования приложения. Хорошая производительность очень желательна. Мне также нужно сохранить данные и перезагрузить.

EDIT2: Получил 1 ответ, поэтому я постараюсь прокомментировать свое мнение. Спасибо, Дорин за твой ответ, но я не думаю, что твоя структура очень удобна. 1) Это не касается иерархии. 2) Наличие отдельных TStringList или TList для каждого узла не очень эффективно для IMO. С этой реализацией я могу только искать данные текущего узла, но не могу эффективно искать во всем дереве.

Я думаю, что эта структура данных должна быть похожа на дерево. У него должны быть узлы с возможностью добавления потомков. Тогда я мог бы просто получить данные узла в событии OnInitNode, проверить, есть ли у моего узла некоторые дочерние элементы, установить флаг ivsHasChildren, если это так, то в событии OnInitChildren установить правильное количество дочерних элементов. Позже в событии OnGetText я мог просто получить необходимые данные из структуры моего узла и установить для него значение CellText на основе индекса столбца. Моя идея состоит в том, чтобы иметь отдельную структуру данных и выполнять все необходимые операции с ней без необходимости использовать VirtualStringTree. Надеюсь, кто-то понял мою точку зрения :).

EDIT3Я нашел довольно интересный модуль JclTrees, который на первый взгляд может быть использован для достижения того, что я ищу. Это принадлежитJCL библиотека. Отсутствие достойной документации затрудняет быстрое изучение его функциональности. Я, вероятно, посмотрю глубже, когда у меня будет больше времени.

 ComputerSaysNo17 янв. 2011 г., 01:09
@David a TList <ваш тип> будет более подходящим ИМХО, но массивы тоже подойдут.
 David Heffernan17 янв. 2011 г., 01:32
@dorin TList - это массив
 David Heffernan16 янв. 2011 г., 23:37
@Linas Не могли бы вы рассказать нам больше о данных, которые вы хотите сохранить. Насколько оно большое? Как это меняется в течение вашего жизненного цикла процесса? Вам нужен произвольный доступ? Каковы ограничения производительности? На данный момент я чувствую, что ваш вопрос слишком общий, чтобы давать содержательные советы.
 David Heffernan16 янв. 2011 г., 23:56
@Linas Произвольный доступ означает, что вам нужен массив.
 ComputerSaysNo17 янв. 2011 г., 01:35
@ Давид да, это массив указателей, НО легче играть :-), это моя точка зрения.

Ответы на вопрос(3)

что вы там вкладываете, я бы предложил создать xsd, описывающий нужную вам структуру, и использовать мастер привязки данных XML для создания кода Delphi, который вы можете использовать.

Эта схема

даст вам эти интерфейсы для работы в Delphi

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:complexType name="itemType">
        <xs:sequence>
            <xs:element name="id" type="xs:int"/>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="itemlist" type="itemlistType" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="itemlistType">
        <xs:sequence>
            <xs:element name="item" type="itemType" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="itemlist" type="itemlistType"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Интересное решение, но я не большой поклонник TXMLDocument из-за его внешних зависимостей.

  IXMLRoot = interface(IXMLNode)
    ['{16C6C960-58B7-400C-9E46-7ACC7BEF276F}']
    { Property Accessors }
    function Get_Itemlist: IXMLItemlistType;
    { Methods & Properties }
    property Itemlist: IXMLItemlistType read Get_Itemlist;
  end;

{ IXMLItemlistType }

  IXMLItemlistType = interface(IXMLNodeCollection)
    ['{59F80BAC-887E-48DF-8288-95276BF9DCE7}']
    { Property Accessors }
    function Get_Item(Index: Integer): IXMLItemType;
    { Methods & Properties }
    function Add: IXMLItemType;
    function Insert(const Index: Integer): IXMLItemType;
    property Item[Index: Integer]: IXMLItemType read Get_Item; default;
  end;

{ IXMLItemType }

  IXMLItemType = interface(IXMLNode)
    ['{1218DD35-C3EF-40E6-831A-1A4AA0782C36}']
    { Property Accessors }
    function Get_Id: Integer;
    function Get_Name: WideString;
    function Get_Itemlist: IXMLItemlistType;
    procedure Set_Id(Value: Inte,ger);
    procedure Set_Name(Value: WideString);
    { Methods & Properties }
    property Id: Integer read Get_Id write Set_Id;
    property Name: WideString read Get_Name write Set_Name;
    property Itemlist: IXMLItemlistType read Get_Itemlist;
  end;
 Mikael Eriksson18 янв. 2011 г., 13:42
Я даже не хочу представить медлительность этого решения.
 Johan20 июн. 2014 г., 14:52
Какая структура данных лучше всего подходит для VirtualString
 Linas18 янв. 2011 г., 12:19
XML по-прежнему является отличной структурой для дерева, поэтому, если вам не нравится TXMLDocument, вы можете использовать что-то еще для доступа и изменения структуры данных XML.

Я предлагаю использовать записи (я не уверен, в какой версии Delphi они добавили методы для записей, я перешел с D7 на D2010), чтобы вы могли получить что-то вроде:

type
  TMyRecordWithMethods = record
    function GetMeAResult: Integer;
    procedure DoSomething(const AInParam: Integer; var AOutParam: Integer);
  end;

если ваша версия Delphi не поддерживает записи с методами и вам действительно нужны методы для узлов, тогда вам придется использовать объекты для достижения этой цели, а также взглянуть на дженерики.

Поскольку вам нужно будет хранить только несколько тысяч предметов, я предлагаю использовать дженерики (имхо не нужно заново изобретать колесо), т.е.

uses ..., Generics.Collections;

type
  TMyNode = class(TObject)// you can leave this out if you like
    MyIntList: TList<Integer>; // you can do lookups, you have to implement your own saving/loading methods
    MyStringList: TStringList or TList<string>; // you can do lookups in both cases, use TStringList for save/load of data
  end;

Теперь я предполагаю, что вы хотели бы сохранить все элементы из виртуального дерева и загрузить их позже, вы можете сделать это, определив свою собственную файловую структуру, т.е.

type
  TMyFileHeader = record
    CountItems: Integer; // number of items in the tree
    ...
  end;

const
  szMyFileHeader = SizeOf(TMyFileHeader);

type
  TMyItemEntry = record
    CountInt: Integer; // number of integer values
    ...
  end;

const
  szMyItemEntry = SizeOf(TMyItemEntry);

теперь вам нужно реализовать загрузку и сохранение, я предлагаю сохранить и загрузить с помощью TFileStream - очень просто,

псевдокод, извините, не время для частичного кода: - \ а) сохранение контента:

сохранить количество элементов в переменной TMyFileHeader и записать его в файл

для каждого элемента в дереве сохраните список целых чисел, сохраните список строк

б) загрузка контента:

читать заголовок файла - чтобы вы знали, сколько элементов нужно прочитать из файла

сделать для индекса: = 0 до подсчета -1 прочитать элемент из файла

Обратите внимание: что вы можете сохранить список строк из каждого элемента непосредственно в текущую позицию в потоке файла, однако было бы целесообразно сохранить его напрямую, используя:

Я надеюсь, что это поможет, фактическая реализация кода зависит от вас, получайте удовольствие!

FileStream.WriteBuffer(PChar(AStringList.Text)^, Length(AStringList.Text) * SizeOf(Char));
это не решает проблему иерархии
 ComputerSaysNo16 янв. 2011 г., 23:07
Вы можете использовать TXMLDocument.
 Linas16 янв. 2011 г., 22:56
@ Давид, давай, мужик, не будь таким защитным :), но в отношении "Тем не менее, объекты не используют больше памяти" - зачем кому-то использовать объекты без полей? То же самое относится и к записям, но если вы добавите одно целочисленное поле в объект и одно целочисленное поле в записи, вы увидите разницу, когда посмотрите на .InstanceSize, теперь, как говорится, умножьте на количество элементов (и подэлементов) и вы получаете много впустую потраченной памяти + процесс создания и освобождения, который займет довольно много циклов ЦП (опять же, если есть много элементов).
 David Heffernan16 янв. 2011 г., 22:53
Я упомянул в своем вопросе, что записи являются довольно хорошим решением, но использование записей не решает некоторые проблемы, как сказал Дэвид.
 ComputerSaysNo16 янв. 2011 г., 22:46
@ Дорин Я ничего не говорил об объектах. Для чего это стоит, я думаю, что записи в порядке. Тем не менее, объекты больше не используют память - TObject не имеет полей-членов. Я хочу сказать, что вопрос заключается в иерархии, а не в том, как хранить информацию в узле.
 David Heffernan16 янв. 2011 г., 22:43
@ Дэвид Хеффернан, в зависимости от своих «реальных» потребностей, он может пойти на компромисс, если ему нужно создать, может быть, миллион узлов, при использовании объектов будет потребляться много памяти (теперь, конечно, все сводится к целевой системе), однако записи будут кушать меньше, ЛЮБОЕ, вы более чем можете прийти с хорошим ответом :-P
Решение Вопроса

потому что данные ответы не решили мои проблемы, я написал свою собственную древовидную структуру данных, которая имитирует TVirtualStringTree и обрабатывает все проблемы, которые я упомянул в своем вопросе. Теперь я могу по желанию использовать только свою структуру данных, и все изменения в ней будут автоматически обновлять VirtualStringTree. Я думаю, что я загружу исходный код где-то позже и выложу ссылку здесь. Спасибо за ответы на все вопросы.

РЕДАКТИРОВАТЬ: Я загрузил источник в код Google:svTrees, Есть небольшая демонстрация, которая показывает, как это работает.

 David Heffernan21 янв. 2011 г., 09:21
Вероятно, попытка объяснить это помогла вам лучше понять проблему! Это часто работает таким образом.
 David Heffernan21 янв. 2011 г., 08:47
Хорошо, что вы все уладили, но я бы прокомментировал, что существенная причина, по которой вы не получили ответ, который вас удовлетворял, заключалась в том, что ваш вопрос был несколько неопределенным.
 Linas21 янв. 2011 г., 09:15
@ Давид Возможно, вы правы, но решение было нелегко реализовать. Может быть, из-за этой сложности мне было нелегко описать мою проблему.

Ваш ответ на вопрос