Быстрый способ подсчета дубликатов в 30000 строк (Libreoffice Calc) - PullRequest
0 голосов
/ 03 ноября 2018

На самом деле у меня уже есть частичный ответ !!! Условное форматирование со значением «Значение ячейки» -> «Дублировать» !!! Таким образом, проверка выполняется для каждой новой записи пользователя в «реальном времени».

Мне нужно проверить, существуют ли повторяющиеся записи в 30000 строках столбца (любое значение, но не пробелы!). Я хотел бы отслеживать, сколько дубликатов в процессе заполнения.

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

Я попробовал формулу:

= СУММПРОИЗВ ((СЧЕТЕСЛИ (F2: F30001; $ F $ 2: $ F $ 30001)> 1))

Работает, но для завершения требуется две минуты.

Если вы хотите повторить мой случай. Мои 30000 записей отформатированы как: буква "A" и цифры от 100000 до 999999, например, A354125, A214547 и т. Д. Скопируйте в виде текста результат "= CONCATENATE (" A "; RANDBETWEEN (100000; 999999))" для сохранения время.

Спасибо!

PS: Кто-нибудь знает алгоритм, используемый для поиска дубликатов в условном форматировании (это быстро)?

Макро-решение не самое лучшее, но приемлемое! ;)

1 Ответ

0 голосов
/ 05 ноября 2018

=SUMPRODUCT((COUNTIF(F2:F30001;$F$2:$F$30001)>1)) должен выполнять следующее: считать, если $F$2 в F2:F30001, затем считать, если $F$3 находится в F2:F30001, ..., затем считать, если $F$30001 находится в F2:F30001. Поэтому он должен полностью зацикливаться на массиве F2:F30001 с каждым отдельным элементом.

Самый быстрый способ подсчета дубликатов в массиве - избежать полного цикла по массиву с каждым отдельным элементом. Одним из способов является сортировка в первую очередь. Есть очень быстрые методы быстрой сортировки. Или используя коллекции, которые по определению могут иметь только уникальные предметы.

Следующий код использует второй способ. Ключи Collection должны быть уникальными. Не удается добавить элемент с повторяющимся ключом.

Public Function countDuplicates(vArray As Variant, Optional inclusive As Boolean ) As Variant
 On Error Goto wrong
 If IsMissing(inclusive) Then inclusive = False
 oDuplicatesCollection = new Collection
 oUniqueCollection = new Collection
 lCountAll = 0
 For Each vValue In vArray
  If contains(oUniqueCollection, CStr(vValue)) Then
   On Error Resume Next
    oDuplicatesCollection.Add 42, CStr(vValue)
   On Error Goto 0
  Else
   oUniqueCollection.Add 42, CStr(vValue)
  End If
  lCountAll = lCountAll + 1
 Next
 countDuplicates = lCountAll - oUniqueCollection.Count + IIF(inclusive, oDuplicatesCollection.Count, 0)
 Exit Function
wrong:
 'xray vArray
 countDuplicates = CVErr(123)
End Function

Function contains(oCollection As Collection, sKey As String)
 On Error Goto notContains
 oCollection.Item(sKey)
 contains = True
 Exit Function
notContains:
 contains = False
End Function

Функция может быть вызвана:

=COUNTDUPLICATES(F2:F30001, TRUE())

Это должно вернуть тот же результат, что и ваш

=SUMPRODUCT((COUNTIF(F2:F30001,$F$2:$F$30001)>1))

Необязательный второй параметр inclusive означает, что в подсчет включены все значения, которые присутствуют несколько раз. Например, {A1, A2, A2, A2, A3} содержит 3 раза A2. Подсчет включительно означает, что результат подсчета будет 3. Подсчет не включительно означает, что результат подсчета будет 2. Имеется 2 раза A2 в качестве дубликата.

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

...