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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 01.10.2015, 10:12   #1
alcaedo
Пользователь
 
Регистрация: 05.09.2015
Сообщений: 28
По умолчанию Удаление дубликатов из массива

Пока опробовал только 2 способа:

1) Функция. Создаётся массив такого-же размера, как исходный, типа boolean.
Исходный массив пробегается от начала к концу. Внутренний цикл от (начала+1) к концу. Если повтор, то в boolean-массиве ставится отметка об удалении элемента по индексу внешнего цикла, а внутренний цикл прерывается (break).
В конце элементы из исходного массива переносятся в Result, учитывая отметки в boolean-массиве.

2) Процедура, принимающая указатель на исходный массив.
Исходный массив пробегается от начала к концу. Внутренний цикл от (начала+1) к концу. Если встретился повтор, то самый последний элемент массива перемещается на место повторяющегося, а размер самого массива уменьшается. После переноса внутренний цикл продолжается с того же самого места, где встретился повтор, ведь перенесённый с конца элемент тоже может оказаться дубликатом.

По моим тестам второй способ раза в 2-3 быстрее. При этом, у меня данные для просеивания такие, что шанс найти дубликаты у рядом расположенных элементов выше.

Поделитесь опытом, может есть способы быстрее. Читал, что из отсортированного массива легче удалять дубли, но не проверял на скорость. Не окажется ли, что сортировка займёт слишком много времени?
alcaedo вне форума Ответить с цитированием
Старый 01.10.2015, 10:26   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

А сравнить? Да и сортировки разные бывают, значит проверить несколько вариантов сортировки. А так просто наобум ни кто не скажет
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 01.10.2015, 10:37   #3
alcaedo
Пользователь
 
Регистрация: 05.09.2015
Сообщений: 28
По умолчанию

Задача не редкая. Должны же найтись люди, которые уже сравнили.
alcaedo вне форума Ответить с цитированием
Старый 01.10.2015, 11:53   #4
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
Задача не редкая. Должны же найтись люди, которые уже сравнили.
Да, например вот ОН.
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 01.10.2015, 14:08   #5
JUDAS
фонатик DELPHI
Форумчанин
 
Аватар для JUDAS
 
Регистрация: 14.01.2008
Сообщений: 714
По умолчанию

Код:
type
  TArray = array of double;



procedure DeleteDuplicate(var A : TArray);
var i,j,count: integer;
begin
  count := High(A);
  for i:=0 to Count do
  begin
    j:=i+1;
    repeat
      if A[i] = A[j] then
      begin
        A[j] := A[count];
        SetLength(A, Count);
        count := High(A);
      end else
      inc(j);
    until j>Count;
  end;
end;
95% сбоев и ошибок приложений, находится в полу метрах от монитора
JUDAS вне форума Ответить с цитированием
Старый 01.10.2015, 15:16   #6
alcaedo
Пользователь
 
Регистрация: 05.09.2015
Сообщений: 28
По умолчанию

JUDAS, так это тоже, что у меня второй вариант.
alcaedo вне форума Ответить с цитированием
Старый 01.10.2015, 15:41   #7
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
размер самого массива уменьшается
Физический размер массива уменьшить один раз в самом конце, а в циклах работать с логическим размером. SetLength очень медленная
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 01.10.2015, 17:27   #8
JUDAS
фонатик DELPHI
Форумчанин
 
Аватар для JUDAS
 
Регистрация: 14.01.2008
Сообщений: 714
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
Физический размер массива уменьшить один раз в самом конце, а в циклах работать с логическим размером. SetLength очень медленная
Можно и так.

Автор, я думал что нужна реализация, а не варианты
3. Перенос уникальный объектов в другой массив. Входная длина запоминается в переменную. Проходя по исходному массиву, ищем уникальные значения во втором массиве. Если таковых нет, в конец результирующего массива добавляем текущий элемент.
95% сбоев и ошибок приложений, находится в полу метрах от монитора
JUDAS вне форума Ответить с цитированием
Старый 02.10.2015, 11:56   #9
SQLPowerUser
Форумчанин
 
Аватар для SQLPowerUser
 
Регистрация: 19.01.2015
Сообщений: 158
По умолчанию

Когда-то находил https://rsdn.ru/forum/delphi/3437315
SQLPowerUser вне форума Ответить с цитированием
Старый 12.10.2015, 14:25   #10
alcaedo
Пользователь
 
Регистрация: 05.09.2015
Сообщений: 28
По умолчанию

Думаю, можно в этой же теме написать.
Вот есть процедура:
Код:
procedure _DupDelete(var SL:TArrayOfSome32ByteType);
var Hsl,N1,N2:int64;
begin
  Hsl:=high(SL);
  N1:=0;
  while N1<Hsl do
    begin
      N2:=N1+1;
      while N2<=Hsl do
        begin
          if SL[N1]=SL[N2] then
            begin
              SL[N2]:=SL[Hsl];
              dec(Hsl);
            end
            else inc(N2);
        end;
      inc(N1);
    end;
  setlength(SL,Hsl+1);
Пытаюсь переписать её на ассемблере. Не могу разобраться, что именно и как лучше передавать в процедуру. Вроде как надо бы передать адрес элемента с индексом 0, проверив предварительно, что массив не пустой. Или лучше передать просто массив? Или адрес массива?

Код:
// использование: SelLength(Massiv,_DupDeleteAsm(addr(Massiv[0])))
function _DupDeleteAsm(SL0:PSome32ByteType):int64;
asm
                                // RAX = Hsl
                                // RBX = N2
                                // RCX = SL
                                // RDX = N1
                                // R8 - для сравнения
                                // R8 и R9 - для пересылки 32 байт
        XOR     RAX,RAX
        TEST    SL0,SL0           // вот тут, возможно, надо проверять массив на nil, если передан сам массив
        JZ      @empty_array     // если массив nil, то выход и возврат RAX:=0
        MOV     RAX,[SL0-8]-1     // Hsl:=high(SL)
        SHL     RAX,5             // в RAX смещение от начала массива
        XOR     RDX,RDX           // N1:=0
  @while01:
        CMP     RDX,RAX           // while N1<Hsl do
        JAE     @finish
        MOV     RBX,RDX           // N2:=N1+1;
        ADD     RBX,32            // в RBX смещение от начала массива
  @while02:
        CMP     RBX,RAX           // while N2<=Hsl do
        JA      @end_of_array
        MOV     R8,[SL0+RDX]      // if SL[N1]=SL[N2] then ...
        CMP     R8,[SL0+RBX]
        JNE     @notEq
        MOV     R8,[SL0+RDX+8]
        CMP     R8,[SL0+RBX+8]
        JNE     @notEq
        MOV     R8,[SL0+RDX+16]
        CMP     R8,[SL0+RBX+16]
        JNE     @notEq
        MOV     R8,[SL0+RDX+24]
        CMP     R8,[SL0+RBX+24]
        JNE     @notEq
                                  // ... then SL[N2] := SL[Hsl]
        MOV     R9,RCX
        ADD     R9,RAX
        FILD    QWORD PTR [R9]    // Load First 8
        FILD    QWORD PTR [R9+8]  // Load Second 8
        MOV     R8,RCX
        ADD     R8,RBX
        FXCH
        FISTP   QWORD PTR [R8]    // Save First 8
        FISTP   QWORD PTR [R8+8]  // Save Second 8
        FILD    QWORD PTR [R9+16] // Load Third 8
        FILD    QWORD PTR [R9+24] // Load Last 8
        FXCH
        FISTP   QWORD PTR [R8+16] // Save Third 8
        FISTP   QWORD PTR [R8+24] // Save Last 8
        SUB     RAX,32            // dec(Hsl), в RAX смещение от начала массива
        JMP     @while02
  @notEq:
        ADD     RBX,32            // inc(N2), в RBX смещение от начала массива
        JMP     @while02
  @end_of_array:
        ADD     RDX,32            // inc(N1), в RDX смещение от начала массива
        JMP     @while01
  @finish:
        SHR     RAX,5             // теперь в RAX количество элементов, а не смещение
        INC     RAX
  @empty_array:
end;
Считаю, удобнее, если функция будет возвращать только размер массива, а само обрезание будет уже в той процедуре, которая вызвала _DupDeleteAsm, по мере надобности

Последний раз редактировалось alcaedo; 12.10.2015 в 16:44.
alcaedo вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Удаление дубликатов с ListBox celovec Общие вопросы Delphi 7 13.09.2016 09:07
Удаление дубликатов SolovejK Общие вопросы Delphi 7 13.03.2015 23:31
Удаление дубликатов Wind-up Bird Microsoft Office Excel 9 02.02.2012 12:49
Удаление дубликатов строк hon Паскаль, Turbo Pascal, PascalABC.NET 10 02.08.2011 05:29
Удаление дубликатов Deltist Microsoft Office Excel 11 14.01.2011 16:01