Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: 1 2 След.
RSS
Перебор строк двумерного массива, способы получить все строки массива
 
Добрый день, планетяне!
Имеется динамический двумерный массив Arr. Чтобы перебрать все его строки, обычно используют способ вроде for i=LBound(Arr) to UBound (Arr).
Возник следующий вопрос: возможно ли то-же самое сделать при помощи for each? Чтобы перебирались не все элементы, а именно все строки.
Изменено: Мартын - 16 Мар 2020 09:39:03
 
Мартын, приветствую!
Приступим:
Цитата
Мартын: for i=LBound(Arr) to UBound (Arr)
двумерный массив с листа всегда будет с единицы + лично я, чтобы не звбывать, что это именно двумерный массив, указываю оба измерения: For i=1 to UBound (Arr, 1)
Цитата
Мартын: возможно ли то-же самое сделать при помощи for each?
For Each… это цикл по всем элементам, соответственно, чтобы через него сделать цикл по строкам, нужно передать массив строк, созданный ручками или в цикле (есть ещё вариант извлечь из адреса регулярками, но это совсем другая тема)

А зачем вам это? В скорости этот метод если и выигрывает, то очень ненамного, но иногда и вовсе проигрывает + нет "встроенного" счётчика, как в For i=1 To …, который очень часто бывает нужен
Изменено: Jack Famous - 16 Мар 2020 09:50:15
Реквизиты для благодарностей — в профиле
 
Нет, т.к. у массива нет определения строк, как отдельного элемента коллекции.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
А для чего нужен такой беребор, даже если таковой найдется , все равно обращаться скорее всего будете к элементу массива по индексу.Можно заполнять коллекцию строчными массивами, а потом по коллекции делать цикл, как вариант.
Изменено: Nordheim - 16 Мар 2020 09:53:02
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Jack Famous написал:
массив с листа всегда будет с единицы
Не совсем отдуплил, что сие значит. Для меня исторически сложилось, что массивы должны начинаться с единицы, поэтому все модули начинаю с обязательных (для меня строк) Option explicit и base 1
Цитата
Nordheim написал:
Можно заполнять коллекцию строчными массивами
Так я этим и пытаюсь заняться, только со словарём. Хочу засунуть строку как элемент словаря, а оно сопротивляется.
Код
Sub test

Dim PlArr As Variant
Dim OnePl As Variant
Dim i As Long
PlArr = ThisWorkbook.Worksheets("PLAN").ListObjects(1).DataBodyRange
For i = LBound(PlArr) To UBound(PlArr)
  OnePl = PlArr(i)
Next
endsub


Почему в строке OnePl = PlArr(i) вылетает Subscript out of range? Массив PlArr создаётся, показывает, что LBound=1, а UBound=1456, но PlArr(1) - out of range!
Что не так? И как засунуть в OnePl всю строку сразу, а не поэлементно.
Изменено: Мартын - 16 Мар 2020 10:14:54
 
Всегда считал, что многомерный массив это массив массивов и для двумерного A(10,10) вызов A(1) должен возвращать одномерный массив, то есть первую строку. Разве в VBA это не так?
 
Всегда считал, что многомерный массив это массив массивов и для двумерного A(10,10) вызов A(1) должен возвращать одномерный массив, то есть первую строку. Разве в VBA это не так?

Цитата
Jack Famous написал:
В скорости этот метод если и выигрывает, то очень ненамного
Это я как раз и проверяю. Недавно наткнулся, что для словаря For each на пару порядков быстрее чем For i.
 
Цитата
Мартын написал:
Недавно наткнулся, что для словаря For each на пару порядков быстрее чем For i.
Для словаря и коллекции да, на обычном массиве я не увидел разницы.
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Мартын написал:
для словаря For each на пару порядков быстрее
потому что для словаря это основополагающий цикл, т.к. он базируется не на индексации, а на элементах.
Цитата
Мартын написал:
массивы должны начинаться с единицы, поэтому все модули начинаю с обязательных (для меня строк) Option explicit и base 1
ну и зря полагаетесь на это, т.к. для VBA исторически сложилось, что массивы с 1. Проверьте вот этот код(хоть option base и равен 1):
Код
Option Explicit
Option Base 1

Sub test_base()
    Dim asp
    asp = Split("1 2 3")
    Debug.Print LBound(asp)
End Sub
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
Мартын написал:
Почему в строке OnePl = PlArr(i) вылетает Subscript out of range?
Посмотрите мерность массива, с листа всегда берется двухмерный, а вы обращаетесь при присвоении к одномерному, в итоге и получаете ошибку
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Nordheim написал:
а вы обращаетесь при присвоении к одномерному
Так в том и вся суть!!! Я хочу получить всю строку массива целиком, а не один его элемент. Я так понимаю в VBA это невозможно, а жаль.
 
Цитата
Дмитрий(The_Prist) Щербаков написал:
Мартын  написал:для словаря For each на пару порядков быстрее потому что для словаря это основополагающий цикл
Господа, это вы о чем? Где в словарях цикл? Ни разу видеть не доводилось.
 
Цитата
Мартын написал:
И как засунуть в OnePl всю строку сразу, а не поэлементно.
Сделать в цикле второй цикл, по строкам массива запоняя одномерный массив, и запихивая его в словарь что то типа
Код
Sub main()
Dim arr(), coll As Object
Dim i&, j&, ikey
arr = tabl
ReDim iarr(UBound(arr, 2))
Set coll = CreateObject("scripting.dictionary")
For i = 0 To UBound(arr)
   arr(i, 1) = i
   For j = 0 To UBound(arr, 2)
      iarr(j) = arr(i, j)
   Next j
   coll.Item(CStr(i)) = iarr
Next i

For Each ikey In coll
    Debug.Print Join(coll.Item(ikey), " | ")
Next ikey
End Sub

Function tabl()
    Dim i&, j&, arr(9, 9)
    For i = 1 To 10
        For j = 1 To 10
            arr(i - 1, j - 1) = i * j
    Next j, i
    tabl = arr
End Function

Но нужно ли это?
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
RAN написал:
Где в словарях цикл
Перебор элементов, можно назвать циклом  :D
"Все гениальное просто, а все простое гениально!!!"
 
Мартын, прочитайте внимательно несколько раз и вопросы снимутся
Реквизиты для благодарностей — в профиле
 
Нет, я, конечно, верю, что метод Exist основан на цикле, но каким боком сей цикл к VBA?
 
Цитата
RAN: верю, что метод Exist основан на цикле
учитывая его скорость, думаю, что там сортировка (при наполнении) и двоичный поиск для извлечения (что, впрочем, не исключает и мини-циклы)
Изменено: Jack Famous - 16 Мар 2020 11:10:20
Реквизиты для благодарностей — в профиле
 
Цитата
RAN написал:
метод Exist основан на цикле
Андрей, ну конечно, речь не про какие-то встроенные в коллекции циклы :) имеется ввиду то, что применение цикла For Each для коллекций и словарей более "родные", чем перебор от 1 до .count.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Добрый день! О каких словарях идет речь?
Код
Sub test()
 Dim dict As Object, i As Long
 Set dict = CreateObject("Scripting.Dictionary")
 
 dict("A") = 1
 
 For i = 1 To dict.Count
   Debug.Print dict(i)
 Next i
 
 Set dict = Nothing
End Sub
Изменено: sokol92 - 16 Мар 2020 11:33:31
Владимир
 
А зачем вообще для словаря
Цитата
Дмитрий(The_Prist) Щербаков написал:
перебор от 1 до .count.
? Ни разу не видел.
 
Цитата
RAN написал:
А зачем вообще
А для коллекции видел? Там оно прям встроенное :) От 1 до .Count в словаре сам не видал в явном исполнении, т.к. там индексация элементов отсутствует. Хотя в определенных случаях придумать можно и такой цикл(например, если заполняем ключи изначально числами). Или когда те же Items сначала были в массив помещены:
Код
Dict.Add "a", "One"
Dict.Add 1, "Two"
Arr = Dict.Items
For i=0 To Dict.Count-1
    MsgBox Arr(i)
Next
придумать-то много чего можно. Даже текущая тема как бы не совсем нужна в контексте массивов :)
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Код
Sub test()
 Dim dict As Object, i As Long
 Set dict = CreateObject("Scripting.Dictionary")
  
 dict("A") = 1
  
 For i = 0 To dict.Count - 1
   Debug.Print dict.Keys()(i)
 Next i
  
 Set dict = Nothing
End Sub
 
Я слышал, что штаны можно через голову надеть. Но зачем???
 
Однажды столкнулся с ситуацией, когда нужно было циклом перебрать элементы коллекции. А коллекция была очень большая. Уже не помню точно, но больше 10 000 элементов. Перебирал циклом For-Nexy. Заметил, что с каждой итерацией перебор идёт все медленнее и медленнее.А после 3000 это стало уже видно невооружённым глазом. Владимир (ZVI).сказал, что при цикле For-Next время на каждую итерацию растёт в геометрической прогрессии и рекомендовал при переборе коллекций использовать For-Each. Применил - результат подтвердил правильность рекомендации.  
 
Цитата
Мартын написал:
Хочу засунуть строку как элемент словаря,
- зачем? И как ключ или значение? Может достаточно "засунуть" индекс строки если нужно значение?
 
Цитата
Hugo написал:
- зачем?
Для дальнейших "извращений".
Цитата
Hugo написал:
И как ключ или значение?
Как значение, естественно.

Общий смысл такой, что я заменяю жуткий SQL запрос, который работает медленно, на "извращения" с массивами и словарями. Работа ускоряется в десятки раз.
В данном случае этот словарь нужен, чтобы связать данные из одной таблицы с другой, через exists.
Суть не в "зачем", а в принципиальной возможности это сделать. Я уже понял, что в VBA невозможно напрямую получить всю строку из двумерного массива. Нашёл способ через WorksheetFunction.Index, потом попробую, приемлемо ли получится по скорости.
 
WorksheetFunction.Index работает медленнее, чем обычный перебор массива.
Ну судя по описанию задачи - кладите как значение индекс строки.
 
Цитата
Hugo: WorksheetFunction.Index работает медленнее, чем обычный перебор массива
может вы о каком-то специфичном применении, конечно, но вообще =ИНДЕКС() отрабатывает очень быстро даже на многотысячных вхождениях
Изменено: Jack Famous - 16 Мар 2020 14:51:32
Реквизиты для благодарностей — в профиле
 
Глянуть бы, полностью что есть и что на выходе, а то прям танцы с бубнами получаются какие-то :)
"Все гениальное просто, а все простое гениально!!!"
 
Jack Famous, я говорю о применении когда пытаются найти данные в массиве.
Страницы: 1 2 След.
Читают тему (гостей: 1)
Наверх