уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Сегодня рассмотрим интересную тему — разработка облака тэгов на Delphi.  Дело в том, что в Интернет полно разного рода php- и js-скриптов по этой теме, а вот до Delphi руки особо у программистов не доходят. Между тем облака тэгов широко используются в программных продуктах, например в блог-клиентах и знание о том, как эти облака строятся будут далеко не лишними.

Прежде, чем приступать к разработке, обратимся к wiki что бы уяснить, что из себя представляет облако тэгов:

визуальное представление списка ярлыков (или категорий). Частота упоминаний, поисков, ссылок в интернете с определенного сайта неких слов, терминов, имен, отображается на специальной странице в виде изображения этих слов в формате гиперссылок. Размер изображения тем больше, чем выше релевантность данного слова (термина, имени)визуальное представление списка ярлыков (или категорий). Частота упоминаний, поисков, ссылок в интернете с определенного сайта неких слов, терминов, имен, отображается на специальной странице в виде изображения этих слов в формате гиперссылок. Размер изображения тем больше, чем выше релевантность данного слова (термина, имени)

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

На вход поступает неструктурированный набор (список) тэгов. Это может быть таблица базы данных или простой список типа TStrings и пр.

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

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

Теперь приступаем к разработке нашего мини-приложения.

1. Подготовка к  разработке облака тэгов на Delphi

Для того, чтобы достигнуть поставленной цели нам необходимо:

  1. Получить список тэгов
  2. Сортировать его, учитывая релевантность каждого тэга, то есть получить пары значений «тэг — количество упоминаний»
  3. Определить размер изображения тэга в облаке
  4. Показать облако пользователю.

Чтобы долго не засиживаться над малозначащими (пока) для нас деталями, будем представлять общий список тэгов в виде списка в TListBox, а для вывода облака — простой RichEdit.

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

Главная форма приложения

Главная форма приложения

В список слева заносится набор тэгов, в RichEdit (он справа сверху) выводится само облако, а снизу в ListBox выносится список тегов отсортированный в порядке упоминания в списке. Последнее сделано просто для наглядности работы приложения. Кроме того, пользователь сам задает минимальный размер шрифта для облака.

2. Разработка «внутренностей» программы.

Итак, первое, что следует зделать — это объявить следующий типы данных:

type
  TCloud = record
    Tag              : string;   //тэг
    Incoming : integer;//количество упоминаний в списке
    FontSize   : integer;//размер шрифта
end;

Собственно этот тип будет у нас основополагающим во всей программе. Теперь добавим глобальные переменные:

var
Cloud   : array of TCloud; //облако тэгов
min_incom: integer; //минимальное число вхождений тэга в список
min_font: integer; //минимальный размер шрифта

Первая процедура, которая сразу приходит на ум — добавление нового тэга в список. Я её реализовал следующим образом:

procedure Add2Cloud(Tag: string);
var i:integer;
incloud: boolean; //true - если тэг есть в облаке
begin
  for I:=0 to length(Cloud)-1 do
    begin
      if Cloud[i].Tag=Tag then
        begin
          inc(Cloud[i].Incoming); //наращиваем число вхождений тэга на 1, если он найден в облаке
          incloud:=true;
          break;
        end;
    end;
  if not incloud then //добавляем новый тэг в облако
     begin
       setlength(Cloud, length(Cloud)+1);
       Cloud[length(Cloud)-1].Tag:=Tag;
       Cloud[length(Cloud)-1].Incoming:=1;
     end;
end;

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

Теперь составим процедуру сортировки облака в порядке возрастания релевантности. Для этого я решил использовать пузырьковый метод сортировки + вставки. На мой взгляд этот метод наиболее прост в реализации и достаточно хорошо себя показывает при работе с небольшими массивами данных. Процедура сортировки облака представлена ниже:

procedure SortCloud;
var i,j: integer;
Temp: TCloud;
begin
{нулевой проход}
//проходим от последнего элемента к первому
  for i:=length(Cloud)-1 downto 1 do
    begin
{нижний элемент меньше ("легче") верхнего - поднимаем его выше}
     if Cloud[i].Incoming<Cloud[i-1].Incoming then
       begin
         Temp:=Cloud[i];
         Cloud[i]:=Cloud[i-1];
         Cloud[i-1]:=Temp;
       end;
    end;
//сортируем оставшуюся часть массива
  i:=length(Cloud)-1;
    repeat
//проход от последнего до j-го элемента сверху
      for j:=length(Cloud)-1 downto length(Cloud)-i do
        begin
          if Cloud[j].Incoming<Cloud[j-1].Incoming then
             begin
               Temp:=Cloud[j];
               Cloud[j]:=Cloud[j-1];
               Cloud[j-1]:=Temp;
             end;
        end;
       i:=i-1;
    until i<=0;
end;

Вначале «поднимаем» наверх элемент облака с самой маленькой релевантностью, а затем продвигаемся «снизу — верх» до n-i-го элемента облака сортируя элементы в необходимом нам порядке. Процедура вывода отсортированного облака в ListBox выглядит следующим образом:

procedure GetSortCloud;
var i:integer;
begin
  SortCloud; //сортируем облако
  ListBox2.Clear; //стираем предыдущий результат
  for i:=0 to Length(Cloud)-1 do
  ListBox2.Items.Add(Cloud[i].Tag+' ('+IntToStr(Cloud[i].Incoming)+')');
end;

Результат сортировки облака в работающей программе будет выглядеть вот так:

tagcloud_2Вначале выписывается тэг, а за ним в скобках — количество упоминаний в общем списке.

По сути дела уже сейчас мы получили на 90% работающую программу, то есть определили главной — пары «тэг — релевантность».

Осталось дело за малым — назначить каждому тэгу свой размер шрифта и вывести все облако в RichEdit.

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

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

procedure GetCloudFonts;
var i:integer;
begin
//определяем минимальное вхождений тегов в облако
  min_incom:=Cloud[0].Incoming;
  for i:=0 to Length(Cloud)-1 do
    if Cloud[i].Incoming<min_incom then
      min_incom:=Cloud[i].Incoming;
  //назначаем размер шрифта для каждой группы
  for i:=0 to Length(Cloud)-1 do
    begin
      if Cloud[i].Incoming=min_incom then
        Cloud[i].FontSize:=min_font
      else
       Cloud[i].FontSize:=min_font+Cloud[i].incoming
    end;
end;

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

procedure PaintCloud;
var i:integer;
begin
  RichEdit1.Clear;
  for i:=0 to Length(Cloud)-1 do
    begin
      RichEdit1.SelAttributes.Size:=Cloud[i].FontSize;
      Randomize;
      RichEdit1.SelAttributes.Color:=RGB(random(255),random(255),random(255));
      RichEdit1.SetSelText(Cloud[i].Tag+' ('+IntToStr(Cloud[i].Incoming)+')'+', ');
    end;
end;

В результате, наше облако тэгов на Delphi будет выглядеть следующим образом:

tagcloud_3

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

Конечно, в строгом смысле это не совсем облако, а скорее заготовка для разработки облака тэгов, но для решения нашей задачи этого вполне достаточно. Кстати, облако тэгов в популярном блог клиенте Zoundary Raven выглядит примерно также :

Raven_tagcloudМожете немного потренироваться и вывести облако отсортированное по алфавиту, как это показано на рисунке. В принципе особых трудностей с сортировкой строковых значений возникнуть у Вас не должно, раз уж вы решили заинтересоваться облаками тэгов на Delphi :) А я тем временем, постараюсь доработать свою программу и получить облако согласно определению из wiki, то есть не просто слова, а гиперссылки на соответствующие статьи. Если получиться — обязательно поделюсь результатами с Вами.

Скачать исходник: Исходники —> Прочие
0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
1 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
trackback

[…] блоге я стараюсь связать теорию с практикой. Например, алгоритм облака тегов на Delphi я сейчас использую в программе "Блевантон" и т.д. […]