Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.10.2014, 13:22   #1
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию Реализация "следящего" поиска для словаря

Здравствуйте, уважаемые.
Решил сделать "оболочку" для найденного в пространствах интернета словаря в txt-формате и в удачной для обработки структуре.

Оболочка простейшая: Edit, ListBox и Memo (потом попробую разобраться с RichEdit, и, если пойму, заменю Memo на него).

Но сейчас меня интересует вот какой вопрос: как осуществить при введении слова в Edit "высвечивание" "ближайшего по алфавиту" в ListBox?

Пробовал две реализации.
Реализация 1:
Код:
procedure TForm1.Edit1Change(Sender: TObject);
var i,j:integer;
begin
  If Edit1.Text<>'' then
  begin
    i:=0;
    while (pos(AnsiLowerCase(Edit1.Text),AnsiLowerCase(ListBox1.Items.Strings[i]))<>1) and (i<ListBox1.Count-1) do inc(i);
    if (i<ListBox1.Count-1) or (pos(AnsiLowerCase(Edit1.Text),AnsiLowerCase(ListBox1.Items.Strings[i]))=1) then
    begin
      ListBox1.ItemIndex:=i;
      ListBox1Click(Sender);
    end;
  end
  else
  begin
    ListBox1.Items.Assign(StringGrid1.Cols[0]);
    ListBox1.ItemIndex:=0;
    ListBox1Click(Sender);
  end;
end;
Реализация 2:
Код:
procedure TForm1.Edit1Change(Sender: TObject);
var i,j:integer;
begin
  If Edit1.Text<>'' then
  begin
    i:=0;
    j:=1;
    While i<ListBox1.Count do
    begin
      if j>1 then if AnsiLowerCase(Edit1.Text)[j-1]<>AnsiLowerCase(ListBox1.Items.Strings[i])[j-1] then
      begin
        ListBox1.ItemIndex:=i;
        ListBox1Click(Sender);
        exit;
      end;
      if pos(AnsiLowerCase(Edit1.Text),AnsiLowerCase(ListBox1.Items.Strings[i]))=1 then
      begin
        ListBox1.ItemIndex:=i;
        ListBox1Click(Sender);
        exit;
      end;
      if AnsiLowerCase(Edit1.Text)[j]<>AnsiLowerCase(ListBox1.Items.Strings[i])[j] then inc(i) else inc(j);
    end;
  end
  else
  begin
    ListBox1.Items.Assign(StringGrid1.Cols[0]);
    ListBox1.ItemIndex:=0;
    ListBox1Click(Sender);
  end;
end;
Первая реализацимя работает хорошо, пока вводящееся слово находится в содержимом слов словаря. Потом начинает тормозить с каждой вводимой буквой, "просматривая" каждый раз весь словарь. Вторая реализация тормозит меньше, но с каждой вводимой буквой. Плюс есть ещё один серьёзный недостаток второй реализации: иногда слова в словаре идут не в алфавитном порядке (я их не сортирую после добавления в ListBox, оставляю в том виде, в каком были в исходном текстовике). И если по второй реализации программа доходит до этого слова, то дальше уже не ищет, т.к. у следующего слова уже другое "начало". Этот нюанс, конечно, серьёзно портит любые способы поиска (кроме первого варианта), поэтому рассматриваются способы для двух случаев:
Случай 1. Данные в ListBox дополнительно не сортируются по алфавиту
Случай 2. Данные в ListBox принудительно сортируются по алфавиту.
Сейчас буду пробовать "модернизировать" первую реализацию, введя массив чисел, равных позициям певых; первых двух и первых трёх букв слова, ограничив таким образом "пролистывание" поиска и сократив время "торможения".
Собственно, сам вопрос:
Как ещё можно сделать поиск по ListBox, чтобы он не тормозил?
Ship_1 вне форума Ответить с цитированием
Старый 07.10.2014, 13:47   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

ListBox1.ItemIndex:=i; и ListBox1Click(Sender); выкинь из цикла. Тогда перерисовки не будет.
Или если нужно с несколькими работать поставь ListBox.Items.BeginUpdate; перед циклом и ListBox.Items.EndUpdate; после.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 07.10.2014, 14:13   #3
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Добавил так:
Код:
    i:=0;
    ListBox1.Items.BeginUpdate;
    while (pos(AnsiLowerCase(Edit1.Text),AnsiLowerCase(ListBox1.Items.Strings[i]))<>1) and (i<ListBox1.Count-1) do inc(i);
    ListBox1.Items.EndUpdate;
    if (i<ListBox1.Count-1) or (pos(AnsiLowerCase(Edit1.Text),AnsiLowerCase(ListBox1.Items.Strings[i]))=1) then
    begin
      ListBox1.ItemIndex:=i;
      ListBox1Click(Sender);
    end;
Тормозить меньше не стало.
ListBox1.ItemIndex:=i; и ListBox1Click(Sender); не в цикле. Они после завершения цикла. ListBox1.ItemIndex:=i; выделяет найденное, ListBox1Click(Sender); отображает статью по слову.
Ship_1 вне форума Ответить с цитированием
Старый 07.10.2014, 17:00   #4
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

Не используй компонент для хранения списка строк.
Список должен быть отсортирован.
Убрать из цикла то, что можно сделать 1 раз до цикла (AnsiLowerCase).
Цикл поиска вытащить в отдельный тред.
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 07.10.2014, 19:45   #5
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Цитата:
Сообщение от min@y™ Посмотреть сообщение
Не используй компонент для хранения списка строк.
Как это? Создавать каждое обращение к процедуре StringList? Вряд ли будет лучше. А если создать только в FormCreate и сделать его глобальным для программы, то при ошибке не сработает Free для списка, что не хорошо. А по ходу выполнения программы таких возможностей может быть не мало. Подобные вещи я стараюсь избегать.

Цитата:
Сообщение от min@y™ Посмотреть сообщение
Список должен быть отсортирован.
Почему? Первый вариант работает и с неотсортированным. Но подтормаживает.

Цитата:
Сообщение от min@y™ Посмотреть сообщение
Убрать из цикла то, что можно сделать 1 раз до цикла (AnsiLowerCase).
Попробую, но сомневаюсь, что убирание одного из двух AnsiLowerCase заметно улучшит ситуацию... А больше, вроде, и нечего убирать.

Цитата:
Сообщение от min@y™ Посмотреть сообщение
Цикл поиска вытащить в отдельный тред.
Не понял слова "тред"...
Ship_1 вне форума Ответить с цитированием
Старый 07.10.2014, 20:16   #6
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

Цитата:
Создавать каждое обращение к процедуре StringList? Вряд ли будет лучше. Почему? Первый вариант работает и с неотсортированным.
Попробую, но сомневаюсь...
Занимаюсь компами 24 года, из них 14 работаю программистом (на заводе, за настоящую зарплату). Поскольку свои выводы ты уже сделал, ответ мой на твои первые 3 коммента будет таким: если не веришь, то и не спрашивай тогда. Чо полез на форум, если умный такой? Советы критиковать? Ну-ну...
Цитата:
Не понял слова "тред"...
Thread
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 07.10.2014, 20:38   #7
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Как это? Создавать каждое обращение к процедуре StringList? Вряд ли будет лучше.
Я тебя огорошу: ListBox1 это тяжелая визуализация этого класса.
Цитата:
А если создать только в FormCreate и сделать его глобальным для программы, то при ошибке не сработает Free для списка, что не хорошо.
А что освободить объект в соответствующем событии формы запрещено?
Цитата:
Подобные вещи я стараюсь избегать.
Отсюда и проблемы. Не то ты избегаешь.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 08.10.2014, 09:57   #8
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Я тебя огорошу: ListBox1 это тяжелая визуализация этого класса.
Не совсем получилось Я знаю, что это визуализация StringList, но не имею представления на сколько тяжёлая.

Цитата:
Сообщение от Stilet Посмотреть сообщение
А что освободить объект в соответствующем событии формы запрещено?
Нет, но как я не могу предусмотреть все возможные события? Каждую процедуру помещать в try..except?

Если не сложно, то можно тогда для лучшего понимания попросить пару слов теории, которую не во всех самоучителях найдёшь?
1. Во всех ли случаях у формы выполняется событие OnClose, или в случае каких-нибудь ошибок программа может прерывать выполнение не обращаясь даже к этой функции?
2. Чем критично не освобождение объекта? В случае программного не освобождения выделяемая ему память очищается только при перезагрузке/выключении компьютера?
3. Что "работает" быстрее? StringList или динамический массив строк?




Цитата:
Сообщение от min@y™ Посмотреть сообщение
...если не веришь, то и не спрашивай тогда. Чо полез на форум, если умный такой? Советы критиковать? Ну-ну...
А чо, уточняющие вопросы для лучшего понимания ответов задавать на форуме запрещено? Тут надо действовать по принципу "что сказали, то и делай, не думая"?

Последний раз редактировалось Ship_1; 08.10.2014 в 10:05.
Ship_1 вне форума Ответить с цитированием
Старый 08.10.2014, 10:09   #9
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

Цитата:
Тут надо действовать по принципу "что сказали, то и делай, не думая"?
Да. Только думая.
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 08.10.2014, 10:30   #10
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Цитата:
Сообщение от min@y™ Посмотреть сообщение
Да. Только думая.
Думая иногда появляются вопросы. Которые я и задаю.
Ship_1 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Постоянно слетает галочка "автоматически" в "Параметры Excel", "Формулы", "Вычисления в книге" Alexsandrr Microsoft Office Excel 4 19.10.2013 14:22
Реализация алгоритма "Решето Сундарама" для поиска простых чисел(Delphi) inviter Помощь студентам 0 12.11.2012 17:15
Создать класс "Фигура", от него наследованием создать 3 класса ("треугольник", "четырехугольник", "окружность") funnyy Помощь студентам 3 17.10.2012 17:40
как задать "мерность" масива и для каждого "измерения" максимальный индекс vova_ Общие вопросы Delphi 5 31.07.2012 22:14
при вводе на листе "магазин"- код товара появлялось "описание" товара из "склада" с "продажной ценой" aleksei78 Microsoft Office Excel 13 25.08.2009 12:04