Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

помогите сравнить два списка [D7, XP]


Dima21   (15.08.17 11:24

Есть два CheckListBox в них содержатся повторяющиеся строки, но они не всегда повторяются, а через какое-то количество строк - чередуются. Необходимо удалить из обоих  CheckListBox повторяющиеся строки и оставить только те строки которые не содержатся один  в другом. я писал так:
1й способ:
procedure TForm1.Button4Click(Sender: TObject);
var x,y: integer;
begin
for x:=0 to CheckListBox1.Count-1 do
 for y:=0 to CheckListBox2.Count-1 do
 begin
   if CheckListBox1.Items.Strings[x]=CheckListBox2.Items.Strings[y] then
     begin
     CheckListBox1.Items.Delete(x);
     CheckListBox2.Items.Delete(y);
     end else exit;
 end;
end;
-------------------------
второй:
procedure TForm1.Button4Click(Sender: TObject);
var x,y: integer;
begin
x:=0;y:=0;
while CheckListBox1.Items.Strings[x]=CheckListBox2.Items.Strings[y] do
     begin
     CheckListBox1.Items.Delete(x);
     CheckListBox2.Items.Delete(y);
     end;
end;
----------------------
первый способ удаляет по одной строчке в каждом CheckListBox
первый и второй способы - удаляет только до первых не одинаковых строчках


KSergey ©   (15.08.17 12:41[1]

В первом варианте две проблемы:
1а) Зачем вот это:
else exit;
?
Вы же здесь явно говорите "если не совпали строки - то выйти из функции", т.е. фактически "перестать сравнивать на первом же несовпадении"

1б) Вы внутри цикла удаляете элементы CheckListBox'ов
Но у дельфи (в отличии от C, например) есть хитрая особенность: границы цикла for вычисляются только один раз, при входе с цикл, и больше границы не перевычисляются.
К чему это приведёт у вас:
Пусть изначально в CheckListBox1  содержит 3 строки. Т.е. Count-1 вычислится равным 2, и i в цикле будет изменяться от 0 до 2 включительно.
Тогда, например будет совпадение в 1-м элементе. Вы его удалите, в CheckListBox1 останется два элемента, верно? но границы цикла for в Delphi не перевычисляются, а значит после этого цикл будет выполняться для CheckListBox1.Items.Strings[2], а это недопустимый индекс, программа взорвётся.
Спасение: можно заменить цикл на while


KSergey ©   (15.08.17 12:43[2]

Во втором варианте не очень понятно что вы хотели сказать. Вы же явно написали: выполнять цикл, пока  нулевые (всегда нулевые? зачем??) элементы двух сисков равны; как только не равны - заканчиваете программу.


Dima21   (16.08.17 02:50[3]

Как мне тогда с помощью while перебрать все элементы списков - какое условие указать (не могу сообразить).
вот, например такие у меня списки:
1     1
2     2
3     3
5     6
7     8
9     0
135  135
208  209
304  304


Sha ©   (16.08.17 09:01[4]

procedure TForm1.Button1Click(Sender: TObject);
var
 i, j: integer;
begin;
 ListBox1.Items.BeginUpdate;
 ListBox2.Items.BeginUpdate;
 for i:=ListBox1.Count-1 downto 0 do begin;
   j:=ListBox2.Items.IndexOf(ListBox1.Items[i]);
   if j>=0 then begin;
     ListBox1.Items.Delete(i);
     ListBox2.Items.Delete(j);
     end;
   end;
 ListBox1.Items.EndUpdate;
 ListBox2.Items.EndUpdate;
 end;


Inovet ©   (16.08.17 09:22[5]

> [3] Dima21   (16.08.17 02:50)
> какое условие указать (не могу сообразить).

для удаления из обоих списков одинаковых элементов что-то такое (не проверял):

procedure TForm1.Button4Click(Sender: TObject);
var
 i1, i2: integer;
 cs: String;

begin
 while i1 < CheckListBox1.Count
 begin
   cs := CheckListBox1.Items[i1];
   i2 := CheckListBox2.IndexOf(cs);
   if i2 > -1
   begin
     while (i2 < CheckListBox2.Count) and (CheckListBox2.Items[i2] = cs)
     begin
       CheckListBox2.Items.Delete(i2);
     end

     while (i1 < CheckListBox1.Count) and (CheckListBox1.Items[i1] = cs)
     begin
       CheckListBox1.Items.Delete(i1);
     end

   end
   else
   begin
     Inc(i1);
   end
 end
end


Dima21   (16.08.17 09:52[6]

Огромное спасибо всем! Проверил от Sha © все работает. А пока вы мне писали я написал свой код - вот он:

procedure TForm1.Button4Click(Sender: TObject);
var x,y: integer;
begin
x:=0;y:=0;
while x<>CheckListBox2.Count do
while y<>CheckListBox2.Count do
if CheckListBox1.Items.Strings[x]=CheckListBox2.Items.Strings[y] then
     begin
     CheckListBox1.Items.Delete(x);
     CheckListBox2.Items.Delete(y);
     end else
       begin
       y:=y+1;
       x:=x+1;
       end;
end;
Но он работает только если в обоих списках одинаковое количество элементов.


Хм   (19.08.17 04:55[7]


> Но он работает только если в обоих списках одинаковое количество
> элементов.


И кроме этого, нужно чтобы одинаковые элементы имели одинаковые индексы, иначе даже с одинаковым кол-вом элементов оно работать не будет.
А при разных кол-вах элементов вообще может зависнуть (зайти в бесконечный цикл.)


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо