массивы

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 983
611
BIT
453
массивы в ЛС можно создавать разными способами и с разными типами содержимого, их DataType будет тоже разными:
V_VARIANT:12
Dynamic array of Variant:8716
Dynamic array of Integer:8706
Dynamic array of Long:8707
Dynamic array of NotesDocument:8739
Dynamic array of NotesViewEntry:8739
Dynamic array of String:8712
Dynamic array of String Initialized:8712
Array of Variant:8204
Array of String:8200
Array of Integer:8194
Array of Long:8195
Array of NotesDocument:8227
Variant empty:0
Variant as String array:8712
код
Код:
    Dim arrV() As Variant, arrI() As Integer, arrL() As Long, arrS() As String _
    , arrC (1) As Variant, arrCS (1) As String, v As Variant, v2arr As Variant _
    , arrSInit() As String, arrND() As NotesDocument, arrNVE() As NotesViewEntry

    v2arr=Split({},{})
    ReDim arrSInit(1) As String

    MsgBox {V_VARIANT:} &Cstr(V_VARIANT) _
    & Chr(10) & {Dynamic array of Variant:} &CStr(DataType(arrV)) _
    & Chr(10) & {Dynamic array of Integer:} &CStr(DataType(arrI)) _
    & Chr(10) & {Dynamic array of Long:} &CStr(DataType(arrL)) _
    & Chr(10) & {Dynamic array of NotesDocument:} &CStr(DataType(arrND)) _
    & Chr(10) & {Dynamic array of NotesViewEntry:} &CStr(DataType(arrNVE)) _
    & Chr(10) & {Dynamic array of String:} &CStr(DataType(arrS)) _
    & Chr(10) & {Dynamic array of String Initialized:} &CStr(DataType(arrSInit)) _
    & Chr(10) & {Array of Variant:} &CStr(DataType(arrC)) _
    & Chr(10) & {Array of String:} &CStr(DataType(arrCS)) _
    & Chr(10) & {Variant empty:} &CStr(DataType(v)) _
    & Chr(10) & {Variant as String array:} &CStr(DataType(v2arr))
а вот где может пригодиться (чтобы эксепшены не ловить)
Код:
Function IsArrayInitialized(arr) As Boolean
    Dim routineName As String
    routineName="IsArrayInitialized"
    On Error GoTo ErrH
    Select Case DataType(arr)
        Case 8192 To  8227:
            IsArrayInitialized = True
        Case 8704 To 8739:
            Dim idx
            idx=-1
            On Error 200 Resume Next
            idx=UBound(arr)
            If idx>=0 Then IsArrayInitialized = True
        Case V_VARIANT:
            IsArrayInitialized = True
    End Select
Quit:
    Exit Function
ErrH:
    Error Err, RaiseError
    Resume Quit
End Function

ЗЫЖ тип возвращаемый из полей документа нотуса будет соответствовать динамическому массиву!
Код:
If Not doc Is Nothing Then Print {Notes String field datatype:} CStr(DataType(doc.Getitemvalue({Form})))
'will Print 8712
 
Последнее редактирование:
  • Нравится
Реакции: Vertigo и alexas1

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 983
611
BIT
453
чтобы уж совсем упростить восприятие - доля петросянства ;)
в табличке по ссылке указаны основные типы, в массивах (как ниже детализировано) типы вычисляются сложением с 8704 (динамический) или 8192 (статический).
Таблица заканчивается (до хэшмапа и массивов)
34User-defined objectV_LSOBJ
35Product objectV_PRODOBJ
последний - это все встроенные нотусевые классы (в примере это видно), хотя могут быть (теоретически) исключения, но я не знаю как проверить
V_LSOBJ - это как и написано - то что сами определили (КОМ не проверял - будет ли он как OLE 9)
т.о. select case обеспечивает перекрытие всех возможный вариантов (я так думаю ;) )
Из теста выше можно так же сделать вывод, что применение Variant, как начального состояния массива, позволит не втыкаться в обработку исключения, т.к. неинициализированный он будет V_EMPTY а после инициализации станет 8704+<datatype>.
Инициализацию Variant, в случае со String, можно производить как split({},{}), дополнять через ArrayAppend или (исходя из типа) через Redim v2arr(1) As String (на мой взгляд менее затратная по процу операция)

List (аки HashMap, по принципу использования) проходят отдельным пунктом, они, подобно java HashMap, могут итерироваться и в массе сценариев их использование упрощает программирование. Есть НО исходя из "природы" - для численных типов их употребление будет нести накладные расходы, если использовать их как ключ. Есть отличие и от HashMap - последовательность элементов, на данный момент, соответствует порядку их занесения в лист
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 983
611
BIT
453
немного про List:
- они чувствительны к регистру (аналогично HashMap), т.е. для обработки ключей с без учета регистра надо кастылять UCase/LCase
- внутри могут храниться различные типа, но работа с ними будет иметь особенности
Код:
Dim map List As Variant, v As Variant, cols List As String
cols({First})={value1}
cols({Second})={value2}
cols({Third})={value3}
v={value4}
map({Row1})=(cols)
forall r in map
  r({Second})=(v)
  Print r({Second})
end forall
вот казалось бы напечатает value4 - "херас-с-два" - вывалит ошибку ;)
---------------------------
IBM Notes
---------------------------
Variant does not contain a container
---------------------------
ОК
---------------------------
присвоение, в этом случае, д.б. через промежуточный Dim tmp List As String:tmp({Second})=(v)
и употребление скобок - это подстраховка (для универсальности - для всех типов) для стринга, ибо - в скрипте стринги передаются по ссылке! (в ф-ции классов - по моему опыту), а скобки указывают на передачу по значению
пример ф-ции класса
Код:
Class ViewNavFlds
    checkMap List As Variant 'for usage in TranslateValues
    checkPath As String

    Function TranslateValue(lst List As Variant, key As String) As String
        On Error GoTo ErrH
        GoTo Begin
ErrH:
        Error Err, RaiseError
Begin:
        'Your code goes here
        Dim v As Variant
        If me.isUCase Then key=UCase(key)
        If (Not IsElement(lst(key))) Then Exit Function

        If Len(checkPath)=0 Then
            checkPath=key
        Else
            'If debug Then PrintMsg({replacement chain:} &checkPath)
        End If
        v=lst(key)
        Dim s As String
        s=v(VALUE_COL)
        checkMap(key)=s

        If InStr(1, s, "@", 5)=1 Then
            ''recursion
            key=StrRight(s,{@})
            checkPath=checkPath &{->} &key
            If IsElement(checkMap(key)) Then Error 1024, {CYCLE REF: } &checkPath
            Me.TranslateValue=Me.TranslateValue(Lst, Key)
        Else
            Erase checkMap
            checkPath={}
            Me.TranslateValue=s
        End If
    End Function
End Class
здесь осуществляется рекурсивный поиск ключа, по которому хранится "окончательное" значение (ссылки указываются через @ следующий ключ)
запуск v=me.fieldsNav.Translatevalue(me.fields, (tag)) и v=me.fieldsNav.Translatevalue(me.fields, tag)дадут разные результаты для tag, первый вариант переменную tag не тронет
 
Последнее редактирование:
  • Нравится
Реакции: alexas1

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 983
611
BIT
453
ибо - в скрипте стринги передаются по ссылке! (в ф-ции классов - по моему опыту)
уточню - по ссылке передается в случае вызова в виде Call (вызов ф-ция всегда осуществляет подобный вызов, в отличии от Sub), пример
Код:
Sub Test(s As String)
    s={value test}
End Sub
Код:
    v={value5}
    Call test(v)
    Print {routine changes:  } v
    v={value5}
    test(v)
    Print {routine changes:  } v
 
  • Нравится
Реакции: Vertigo

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
232
ЗЫЖ тип возвращаемый из полей документа нотуса будет соответствовать динамическому массиву!
Писал когда-то об этом.

уточню - по ссылке передается в случае вызова в виде Call (вызов ф-ция всегда осуществляет подобный вызов, в отличии от Sub)
Конкретно об этом, помню, писала ещё Лена Осмоловская на заре этого форума.
И с промежуточной переменной в цикле со списками уже проходили)

Решил переписать всё по массивам и спискам в отдельной теме? :)
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 983
611
BIT
453
Решил переписать всё по массивам и спискам в отдельной теме?
собрать особенности..., эти грабли не очевидны
и о передаче по значению (в ф-ции) могут не знать лотусисты
вот еще кусочек ;) к слову о передачах по рефу (которой нет)
Код:
    cols({Second})={value2}
    map({Row1})=cols
    cols({Second})={value3}
    map({Row2})=(cols)
    'change initial list
    cols({Second})={value5}
    Dim row
    row=map({Row1})
    Dim s As String
    s=s & {After Row1 ref array has been chaged:} &row({Second}) &Chr(10)
    row=map({Row2})
    s=s & {After Row2 ref array has been chaged:} &row({Second}) &Chr(10)
    s=s & {Initial list value:} &cols({Second})
    Msgbox(s)
Т.е. конкретно получаем копирование мапа!
Для любого массива будет аналогично (копирование) - что может пригодиться в некоторых сценариях, объекты не тестил
 
Последнее редактирование:

Mikle_GB

Lotus Team
07.07.2016
70
25
BIT
63
Давеча поспорил с коллегой, по каким структурам быстрее искать данные. Он топил за arrayGetIndex, который будет быстрее намного; я утверждал, что обращение по ключу листа будет немного быстрее. Оба ошиблись. Заполнение листа 16000 средних строк (фио, адреса) в полтора раза дольше массива, а поиск на 3 порядка быстрее (isElement). Имейте в виду, есчто. Есессно, я искал как присутствующие строки, так и отсутствующие.
Кстати, Майк забыл упомянуть ограничения на длину массивов в скрипте: он должен поместиться в 64к (см по типу; строки это суть указатель, то есть 4 байта). Вот почему 16000 было элементов.
Лист в памяти - это просто двусвязный список, но судя по скорости поиска, дополненный каким-то деревом.
 
  • Нравится
Реакции: VladSh и lmike

savl

Lotus Team
28.10.2011
2 624
314
BIT
517
Давеча поспорил с коллегой, по каким структурам быстрее искать данные. Он топил за arrayGetIndex, который будет быстрее намного; я утверждал, что обращение по ключу листа будет немного быстрее. Оба ошиблись. Заполнение листа 16000 средних строк (фио, адреса) в полтора раза дольше массива, а поиск на 3 порядка быстрее (isElement). Имейте в виду, есчто. Есессно, я искал как присутствующие строки, так и отсутствующие.
Кстати, Майк забыл упомянуть ограничения на длину массивов в скрипте: он должен поместиться в 64к (см по типу; строки это суть указатель, то есть 4 байта). Вот почему 16000 было элементов.
Лист в памяти - это просто двусвязный список, но судя по скорости поиска, дополненный каким-то деревом.
А массив при этом фиксированный был или динамический?
Если фиксированный, то я догадываюсь, почему это быстрее.
 

Mikle_GB

Lotus Team
07.07.2016
70
25
BIT
63
Если фиксированный, то я догадываюсь, почему это быстрее.
Массив был динамический - в статический только 8 тысяч строк помещалось... точнее 8185: Dim ar(0 To 8184) As String ещё прокатывает. А почему фиксированный должен быть медленнее?
 

savl

Lotus Team
28.10.2011
2 624
314
BIT
517
Массив был динамический - в статический только 8 тысяч строк помещалось... точнее 8185: Dim ar(0 To 8184) As String ещё прокатывает. А почему фиксированный должен быть медленнее?
не, фиксированный как раз быстрее. Так как память не выделяется на каждой итерации.
 
  • Нравится
Реакции: VladSh

Mikle_GB

Lotus Team
07.07.2016
70
25
BIT
63
не, фиксированный как раз быстрее. Так как память не выделяется на каждой итерации.
Обижаешь, начальник. Память под указатели выделялась заранее redim arr(1 to 32767) as string, сами строки понятно при присвоении выделялись.
Кста, 32767 это как бы лимит для динамического масссива - индексация через signed int сделана. "Как бы" - потому что можно и так работать:
Const iMax= 32767
Redim arr(-iMax To iMax) As String
То есть фактически 65500 значений можно хранить в массиве, если приспичит. На таком объёме заполнение листа идёт почти в 2 раза дольше, чем массива, но поиск по-прежнему мгновенный.
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
232
...а поиск на 3 порядка быстрее (isElement).
Лист в памяти - это просто двусвязный список, но судя по скорости поиска, дополненный каким-то деревом.
Думаю, там идёт просто обращение к элементу по хешу, а если его нет, то ошибка отсутствия элемента отлавливается функцией IsElement и возвращается False.
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 983
611
BIT
453
Давеча поспорил с коллегой, по каким структурам быстрее искать данные. Он топил за arrayGetIndex, который будет быстрее намного; я утверждал, что обращение по ключу листа будет немного быстрее. Оба ошиблись. Заполнение листа 16000 средних строк (фио, адреса) в полтора раза дольше массива, а поиск на 3 порядка быстрее (isElement). Имейте в виду, есчто. Есессно, я искал как присутствующие строки, так и отсутствующие.
Кстати, Майк забыл упомянуть ограничения на длину массивов в скрипте: он должен поместиться в 64к (см по типу; строки это суть указатель, то есть 4 байта). Вот почему 16000 было элементов.
Лист в памяти - это просто двусвязный список, но судя по скорости поиска, дополненный каким-то деревом.
а вот кста - вариант с кэйс сенситив рассматривали?
ведь для поиска в листе понадобится преобразование, как при наполнении, так и при поиске!
 

Mikle_GB

Lotus Team
07.07.2016
70
25
BIT
63
а вот кста - вариант с кэйс сенситив рассматривали?
ведь для поиска в листе понадобится преобразование, как при наполнении, так и при поиске!
Ну, если добавить lcase в каждое обращение к ключу листа - получается на 13 тысячах строк заполнение 249 вместо 218 мс, поиск - 172 вместо 125; на 26 тысячах - 780 вместо 733 и 343 вместо 312.
Не критично полюбому) интересно, что время заполнения растёт хуже, чем линейно, а поиска - лучше.
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 983
611
BIT
453
Ну, если добавить lcase в каждое обращение к ключу листа - получается на 13 тысячах строк заполнение 249 вместо 218 мс, поиск - 172 вместо 125; на 26 тысячах - 780 вместо 733 и 343 вместо 312.
Не критично полюбому) интересно, что время заполнения растёт хуже, чем линейно, а поиска - лучше.
дык у мапов либо константа либо логарифм на поиск, а вот общая сложность (наполнение) O( n ) до O(n^2)
т.е. с реализацией наполнения - что-то недоработали ;)
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 983
611
BIT
453
Обижаешь, начальник. Память под указатели выделялась заранее redim arr(1 to 32767) as string, сами строки понятно при присвоении выделялись.
Кста, 32767 это как бы лимит для динамического масссива - индексация через signed int сделана. "Как бы" - потому что можно и так работать:
Const iMax= 32767
Redim arr(-iMax To iMax) As String
То есть фактически 65500 значений можно хранить в массиве, если приспичит. На таком объёме заполнение листа идёт почти в 2 раза дольше, чем массива, но поиск по-прежнему мгновенный.
а вот здесь может выстрелить 2Гб на процесс в 32 разряда
т.е. строки под 32000 символов ;) ASCII на элемент
что кажется объемным, но практически недостижимо ибо в общем пространстве всего ЛС
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!