Что нового

Быстрое удаление элементов массива

dumoed

Знающий
Сообщения
34
Репутация
5
Версия AutoIt
3.3.14.0
Версия
3.3.14.0
Решил поделитьсяю
Есть массив, в нем есть строки с "плохими" элементами их надобно найти и изничтожить, а теперь вопрос к знатокам, как сделать это быстро? Был предложен вот такой код, который, вполне надежный

Код:
Func SearchAndDeleteFromArray($aArray, $sSearchText)
Local $iCount = UBound($aArray) - 1 ;определяем количество элементов в массиве
For $i = $iCount To 0 Step -1 ; проходимся по массиву в обратном порядке, чтобы не изменять индексы элементов
If StringInStr($aArray[$i], $sSearchText) Then ; если текущая строка содержит заданный текст
 _ArrayDelete($aArray, $i) ; удаляем эту строку из массива
EndIf
Next
Return $aArray ; возвращаем измененный массив
EndFunc

но меня интересовал вопрос как это сделать с помощью _ArrayFindAll и _ArrayDelete

В процессе изучения выяснилось, что функция _ArrayFindAll , несколько кривовата по отношения к _ArrayDelete.
ArrayFindAll выдает одномерный массив со списком найденных строк где находится "плохой" элемент, эти номера строк (вот тут внимание) перечисляются, начиная с 0го элемента выдаваемого одномерного массива. А ArrayDelete (как выяснилось из английской справки) в качестве параметра понимает список-массив, где 0-м элементом идёт счётчик, другими словами Ubound этого массива, а далее, начиная с первого элемента перечисляются строки с найденными "плохими" элементами.
От какого лешего разрабы Array не состыковали их между собой, неясно. Ещё бы русскую справку по _ArrayDelete неплохо поправить.
Сообщение автоматически объединено:

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

Код:
$search=_ArrayFindAll($aArray,'Плохой элемент',0,0,0,0,4) ; ищем "плохие" элементы, 4 номер столбца в $aArray, массива в котором ищем и удаляем "плохой" элемент , на выходе получаем одномерный массив, который пока нельзя использовать в качестве параметра в _ArrayDelete
    $ss=UBound($search)

    Dim $searchwithcount[$ss+1] ; объявляем новый правильный одномерный массив

            For $b=0 to UBound($search)-1
            $searchwithcount[$b+1]=$search[$b] ;сдвигаем элементы неправильного массива на строку вниз, чтобы в 0-ю вставить нужный счетчик
            Next

    $searchwithcount[0]=$ss ;вставляем счетчик

        _ArrayDelete ($aArray,$searchwithcount) ; теперь удаляем список строк с "плохими" элементами, но уже используем правильный одномерный массив с счетчиком в 0м элементе списка
        _ArrayDisplay ($aArray) ;смотрим, что получилосьj

Сообщение автоматически объединено:

еще интересный вариант с преобразованием найденного одномерного массива с плохими элементами в строку c последующим ее скармливанием _ArrayDelete

Код:
local $aArray[6] = [1,2,3,2,5,2] 
$aDel = _ArrayFindAll($aArray , 2)
_ArrayDelete($aArray , _ArrayToString($aDel , ";"))
_ArrayDisplay($aArray)
 
Последнее редактирование:

RaZum

Знающий
Сообщения
78
Репутация
14
Map возможно будет более актуален в таких случаях.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
но меня интересовал вопрос как это сделать с помощью _ArrayFindAll и _ArrayDelete
нужно немного иначе - найти оптимальное решение для конкретной задачи. Возможно, придется что то написать самому.
Код:
_ArrayFindAll и _ArrayDelete

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

Код:
#include <Array.au3>

Local $aArray[2000]
For $i = 0 To UBound($aArray) - 1 ; заполняем массив
    Switch $i
        Case 4, 258, 500, 672, 1563, 1965
            $aArray[$i] = 'sss'
        Case Else
            $aArray[$i] = $i
    EndSwitch
Next
_ArrayDisplay($aArray, 'До')
Local $sResult = _SearchDellString($aArray, 'sss')
_ArrayDisplay($aArray, 'После')
If $sResult <> '' Then MsgBox(64, 'Очищено', 'Номера индексов' & @LF & $sResult)

Func _SearchDellString(ByRef $aArrayIn, $Value)
    Local $aArrayTmp[0], $sString = ''
    For $i = 0 To UBound($aArrayIn) - 1
        If String($aArrayIn[$i]) = $Value Then ; представляет значения в виде строки
            $sString &= $i & ', '
            ContinueLoop
        Else
            ReDim $aArrayTmp[UBound($aArrayTmp) + 1]
            $aArrayTmp[UBound($aArrayTmp) - 1] = $aArrayIn[$i]
        EndIf
    Next
    If UBound($aArrayTmp) - 1 > 0 Then $aArrayIn = $aArrayTmp
    Return $sString
EndFunc   ;==>_SearchDellString
 
Последнее редактирование:
Автор
D

dumoed

Знающий
Сообщения
34
Репутация
5
Map возможно будет более актуален в таких случаях.
Да, это уже проверено, но, к сожалению, Map пока не овладел, буду пробовать
Сообщение автоматически объединено:

Код из первого поста, но в виде функции, в одномерном массиве $aArray ищет в строках подстроки $sSearchText и где находит удаляет строки

Код:
Func DeleteFindAll($aArray, $sSearchText) ; массив, строка для удаления
    Local $search=_ArrayFindAll($aArray,$sSearchText,0,0,0,1)
    Local $ss=UBound($search)
    Dim $searchwithcount[$ss+1]
    For $b=0 to UBound($search)-1
        $searchwithcount[$b+1]=$search[$b]
    Next
    $searchwithcount[0]=$ss
    _ArrayDelete ($aArray,$searchwithcount)
    Return $aArray
EndFunc


Для двумерных массивов

Код:
Func DeleteFindAll($aArray, $sSearchText, $Column) ; массив, строка для удаления, номер столбца где искать
$search=_ArrayFindAll($aArray, $sSearchText,0,0,0,1, $Column) ; ищем "плохие" подстроки в столбце $Column двумерного массива $aArray, на выходе получаем одномерный массив, который пока нельзя использовать в качестве параметра в _ArrayDelete
$ss=UBound($search)
Dim $searchwithcount[$ss+1] ; объявляем новый правильный одномерный массив
For $b=0 to UBound($search)-1
$searchwithcount[$b+1]=$search[$b] ;сдвигаем элементы неправильного массива на строку вниз, чтобы в 0-ю вставить нужный для _ArrayDelete счетчик
Next

$searchwithcount[0]=$ss ;вставляем счетчик

_ArrayDelete ($aArray,$searchwithcount) ; теперь удаляем список строк с "плохими" элементами, но уже используем правильный одномерный массив с счетчиком в 0м элементе списка
Return $aArray; получаем почищенный массив
EndFunc

_ArrayDisplay ($aArray) ;смотрим, что получилось
 
Последнее редактирование:
Верх