Форум программистов, компьютерный форум, киберфорум
Наши страницы
Lotus Notes/Domino: Программирование
Войти
Регистрация
Восстановить пароль
 
 
Dorkyr
0 / 0 / 0
Регистрация: 12.01.2009
Сообщений: 246
#1

Вопросы по работе со строками - Lotus

25.08.2010, 07:53. Просмотров 29900. Ответов 27
Метки нет (Все метки)

Наверняка поднимаю "избитую" тему.
Пример задачи, необходимо пройтись по коллекции, достать из каждого документа данные. В конце обработки получить строку с данными из коллекции.
Напрашивается очевидный метод обхода:

LotusScript
1
2
3
4
5
6
7
8
...
Dim s as String
while not doc is nothyng
...
s=s+doc.GetitemValue("TestField")(0)
...
wend
...
А есть альтернативный подход: собрать массив строк, затем в конце массив объединить в строку

LotusScript
1
2
3
4
5
6
7
8
9
10
11
12
...
Dim i as long
i=0
while not doc is nothyng
...
Redym preserve s(i) as string
s(i)=doc.GetitemValue("TestField")(0)
i=i+1
...
wend
s1=join(s)
...
Методом профилирования кода (который был в агенте), мною было замечено, что второй подход отрабатывает намного быстрее. В попытках объяснить сей факт не хочу выглядеть дилетантом, поэтому нуждаюсь в Вашем мнении об этом. (Подозреваю, что загвоздка с работой с памятью).
В связи с этим, написал класс для работы со строками. И перед тем как, его использовать "в производстве", прошу вас выявить недостатки:

LotusScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
Public Class PROTOTYPE_STRING
Private stringArray() As String                                                 Массив строк
Private extStringArray() As String                                              Вспомогательный массив, на случай если превысит лимит массива или лимит строки в байтах(если включен игнор лимита)
Private i As Integer                                                                    Счетчик для основного массива
Private j As Integer                                                                    Счетчик для вспомогательного массива
Private stringLength As Double                                              Счетчик размера строки в байтах
Private isToCheckLength As Boolean                                      Флаг о необходимости проверки превышения лимита строки в байтах
Private isToIgnoreLimit As Boolean                                          Флаг об игнорировании превышения лимита строки в байтах
Private isOutOfLimit As Boolean                                             Флаг о превышении лимита строки в байтах
 
Public Sub New                                                                      Конструктор
Truncate                                                                            Зануляем все переменные
Me.isToCheckLength=True                                                 Делаем необходимым проверку превышения лимита строки в байтах
Me.isToIgnoreLimit=False                                                    Отказываемся об игнорирования превышения лимита строки в байтах
End Sub
 
Public Property Get ToCheckLength As Boolean
ToCheckLength=Me.isToCheckLength
End Property
 
Public Property Set ToCheckLength As Boolean
Me.isToCheckLength=ToCheckLength
End Property
 
Public Property Get ToIgnoreLimit As Boolean
ToIgnoreLimit=Me.isToIgnoreLimit
End Property
 
Public Property Set ToIgnoreLimit As Boolean
Me.isToIgnoreLimit=ToIgnoreLimit
If Me.isToIgnoreLimit Then Me.isToCheckLength=True          Если игнорируем превышения лимита строки в байтах, то делаем необходимым проверку превышения лимита строки в байтах
End Property
 
Public Sub Truncate
Erase Me.stringArray                                                            Зачищаем массив строк
Erase Me.extStringArray                                                     Зачищаем вспомогательный массив строк
Me.i=0                                                                              Зануляем счетчик массива строк
Me.j=0                                                                              Занулям счетчик вспомогательного массива
Me.stringLength=0                                                               Зануляем счетчик размера строки в байтах
Me.isOutOfLimit=False                                                       Предполагаем, что лимит строки в байтах не превышен
End Sub
 
Public Function Add(stringToAdd As String) As Boolean
On Error Goto erH
Add=True
If Me.isToCheckLength Then                                              Если нуждается в проверке превышения лимита строки
Dim currentStringLength As Long
currentStringLength=Lenb(stringToAdd)                           Берем размер текущей строки в байтах
Me.stringLength=Me.stringLength+currentStringLength Прибавляем его к основному счетчику размера строки в байтах
If (Me.stringLength)>2147483647 Then                            Если превысил лимит строки
If Me.isToIgnoreLimit Then                                          Если игнорируем ограничения,
me.isOutOfLimit=True
ThrowToExt                                                          то перекидываем содержимое массива, в вспомогательный массив, объединяя в строку
Me.stringLength=0                                                   зануляем счетчик размера строки в байтах
Else                                                                            иначе
Msgbox "Превышен лимит строки в 2G!"                показываем сообщение о превышении,
Add=False
Exit Function
End If
End If
End If
Redym Preserve Me.stringArray(Me.i) As String
Me.stringArray(Me.i)=stringToAdd                                        Даем новому элементу массива значение текущей строки
Me.i=Me.i+1
If Me.i=32767 Then ThrowToExt                                           Если превысит лимит массива, то перекидываем содержимое массива строк в вспомогательный массив, объединяя в строку
exF:    Exit Function
erH:    Msgbox Error + " in "+Getthreadinfo(1)+" on line "+Cstr(Erl)
Resume exF
End Function
 
Private Sub ThrowToExt
Redym Preserve extStringArray(Me.j) As String
extStringArray(Me.j)=Join(Me.stringArray,Chr(10))                   Перекидываем содержимое массива строк в вспомогательный массив, объединяя в строку
Me.j=Me.j+1
Erase Me.stringArray                                                            Зачищаем массив строк
Me.i=0
End Sub
 
Public Function Value As Variant
On Error Goto erH
ThrowToExt                                                                      Перекидываем содержимое массива строк в вспомогательный массив, объединяя в строку
If Me.isOutOfLimit Then                                                     Если превысил лимит строки в байтах,
Value=Me.extStringArray                                                 то возвращем вспомогательный(объединенный) массив строк
Else                                                                                    иначе
Value=Join(Me.extStringArray,Chr(10))                               Возвращаем вспомогательный массив строк, объедененный в строку
End If
exF:    Exit Function
erH:    Msgbox Error + " in "+Getthreadinfo(1)+" on line "+Cstr(Erl)
Value=""
Resume exF
End Function
 
Sub Delete
Truncate
End Sub
End Class
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.08.2010, 07:53
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Вопросы по работе со строками (Lotus):

Вопросы по работе с БД
Всем доброго времени! Хотелось бы узнать два основных вопроса. 1. Не могли бы...

ВопросЫ по функциям для работы со строками с++
Вот я нашел большинство (если не все) стандартные функции C++ для работы со...

Вопросы по работе с MsSql
Всем привет. Прошу помощи в проблеме так как даже не знаю как ее гуглить иначе...

Вопросы по работе процессора
Есть такой вопросы : 1)Действия процессора при операциях передачи данных...

Вопросы по работе с датами
Вот такие вопросы: 1. Как сравнить два значения времени 2. Как достать текст...

Вопросы по работе с ИК приемником
Блиц-опрос: 1. ИК приемник принимает сигналы от ДУ пульта, как он узнает какая...

27
mvyush
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 2,219
25.08.2010, 09:18 #2
В java класс, реализующий такой подход работы со строками, называется StringBuffer. Где-то на форуме натыкался на реализацию на LS. КМК там было проще.

http://www.nsftools.com/blog/blog-10-2007.htm#10-12-07
Только я не совсем согласен с приведённым там графиком. Если нужно собрать относительно короткую строку из подстрок, конкатенация работает всё-таки быстрее.
0
Mydyvys
0 / 0 / 0
Регистрация: 04.12.2004
Сообщений: 3,329
25.08.2010, 09:42 #3
http:///ipb.html?s=&sh...st&p=168091
0
Omh
0 / 0 / 1
Регистрация: 30.06.2007
Сообщений: 2,153
25.08.2010, 11:01 #4
Цитата Сообщение от Darker
while not doc is nothyng
Redym preserve s(i) as string
А если ты ещё не будешь редимить массив каждый раз в цикле, а объявишь сразу по количеству документов в коллекции, будет ещё быстрее
0
mvyush
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 2,219
25.08.2010, 11:16 #5
Можно и такое попробовать:

LotusScript
1
2
3
4
5
6
7
8
9
10
11
12
...
Dim session As NotesSession
Dim stream As NotesStream
Set stream = session.CreateStream
Do Until doc Is Nothyng
...
stream.WriteText(doc.GetitemValue("TestField")(0))
...
Loop
stream.Position = 0
s1 = stream.ReadText
...
0
Dorkyr
0 / 0 / 0
Регистрация: 12.01.2009
Сообщений: 246
25.08.2010, 12:25 #6
Omh
Попробовал твой вариант, такой же результат по времени
nvy
приходило в голову, но если быть дотошным, то этот способ медленнее на 20-40%(без учета создания сессии и потока)
0
VtodSh
0 / 0 / 0
Регистрация: 07.12.2009
Сообщений: 1,197
11.10.2010, 15:28 #7
Цитата Сообщение от lmike
а вот тормоза в реализации стринговых операций в LS - известный момент
Для быстрой конкатенации на больших строках очень помогает StringBuffer, в остальном - то да...
0
ToxoRot
0 / 0 / 0
Регистрация: 04.11.2007
Сообщений: 3,019
11.10.2010, 18:37 #8
Цитата Сообщение от VladSh
Для быстрой конкатенации на больших строках очень помогает ]]>StringBuffer]]>, в остальном - то да...
а результаты производительности опубликуй тут ;)
0
Dorkyr
0 / 0 / 0
Регистрация: 12.01.2009
Сообщений: 246
12.10.2010, 07:37 #9
2 минуса класса StringBuffer:
a) при превышении лимита массива (default 32000) происходит конкатенация(при частом превышении чревато тормозами)
б) лимит выдачи строки в 2GB

я опубликовывал свой вариант, там это все учтено
Если size>2Gb, возвращается массив, иначе строка
0
VtodSh
0 / 0 / 0
Регистрация: 07.12.2009
Сообщений: 1,197
12.10.2010, 18:05 #10
Цитата Сообщение от Darker
a) при превышении лимита массива (default 32000) происходит конкатенация(при частом превышении чревато тормозами)
он не превышается, т.к. это контролируется в resetArray



Цитата Сообщение от Darker
б) лимит выдачи строки в 2GB
Мне кажется, что это теория... Попробуйте Streamом открыть 50-100-метровый файл и добавить его раз 7... как раз здесь упираемся в ограничение массива 65536, а если файл больше 100 метров, то и того меньше.


ToxaRat
Результаты производительности давались . Тестовый пример, который идёт с классом, у меня показал 10-тикратное превышение скорости.
0
rymsk
0 / 0 / 0
Регистрация: 12.11.2009
Сообщений: 882
12.10.2010, 19:41 #11
Цитата Сообщение от VladSh
Тестовый пример, который идёт с классом, у меня показал 10-тикратное превышение скорости.
на какой версии?
тут интересная инфа:
http://blog.vinceschuurman.com/home/ndt4.n...nk=201005212259
0
VtodSh
0 / 0 / 0
Регистрация: 07.12.2009
Сообщений: 1,197
12.10.2010, 20:34 #12
rinsk
Не сервер. 8.5.2 клиент.

По памяти говорил, ошибся.. Только что прогнал, вот такие результаты:
Final string buffer length = 100001. Timer = ,4453125 sec.
Final string length = 100001. Timer = 11,53906 sec.
0
Dorkyr
0 / 0 / 0
Регистрация: 12.01.2009
Сообщений: 246
13.10.2010, 07:32 #13
VladSh

Public Function toString () As String
** if thys has to be compatible with Notes R5 or lower, use:
toString = buffer & r5Join(tempArray, "")

** for Notes 6 and higher, you can use:
toString = buffer & Join(tempArray, "")
End Function


** append any kind of variable that can be converted to a String
Public Sub append (v As Variant)
If (pos > upperB) Then
buffer = Me.toString
Me.resetArray(Clng(upperB) * 2)
End If

tempArray(pos) = Cstr(v)
pos = pos + 1
End Sub


в случае если

LotusScript
1
(pos > upperB)
, вызывается

LotusScript
1
buffer = Me.toString
, где происходит конкатенация старого буфера с темповым массивом toString = buffer & Join(tempArray, "")



Цитата Сообщение от VladSh
Мне кажется, что это теория...
я с таким сталкивался когда подписывал вложения
0
mvyush
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 2,219
13.10.2010, 09:26 #14
Цитата Сообщение от VladSh
По памяти говорил, ошибся.. Только что прогнал, вот такие результаты:
Final string buffer length = 100001. Timer = ,4453125 sec.
Final string length = 100001. Timer = 11,53906 sec.
По тесту, приведённому там, получал аналогичные результаты. Только в том тесте в одну и ту же строку конкатенировали 100000 раз. Если же взять 10 конкатенаций и повторить опыт 10000 раз (число операций конкатенации будет таким же), время выполнения будет совсем другим, не в пользу StringBuffer. Так что я бы не стал везде и всюду вместо конкатенации использовать StringBuffer.
0
Dorkyr
0 / 0 / 0
Регистрация: 12.01.2009
Сообщений: 246
13.10.2010, 11:21 #15
Цитата Сообщение от nvy
Если же взять 10 конкатенаций и повторить опыт 10000 раз (число операций конкатенации будет таким же), время выполнения будет совсем другим, не в пользу StringBuffer.
код в студию, чтобы понять
0
mvyush
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 2,219
13.10.2010, 12:06 #16
Искать лень. А суть примерно такая: сравнивать время выполнения не

Код
s = ""
For i = 1 To 100000
s = s + "a" аналогично для StringBuffer
Next
а

Код
For j = 1 To 10000
s = ""
For i = 1 To 10
s = s + "a" аналогично для StringBuffer
Next
Next
0
Dorkyr
0 / 0 / 0
Регистрация: 12.01.2009
Сообщений: 246
13.10.2010, 12:22 #17
Получается в конце StringBuffer нам выдаст ааааааааааааа......аа, а традиционный способ лишь аааааааааа,
Как-то нечестно получается
0
mvyush
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 2,219
13.10.2010, 12:33 #18
Цитата Сообщение от Darker
Получается в конце StringBuffer нам выдаст ааааааааааааа......аа, а традиционный способ лишь аааааааааа,
Как-то нечестно получается
Я внутренний цикл оформлял функцией. И StringBuffer и конкатенация собирали "аааааааааа", но много раз. Более того, я также пробовал "выкусывать" функционал StringBufferа, то есть сразу создавал массив нужного размера и потом joinил его. Во всех случаях конкатенация выигрывала. Экспериментировал для типично собираемых сообщений msgbox.
0
VtodSh
0 / 0 / 0
Регистрация: 07.12.2009
Сообщений: 1,197
13.10.2010, 14:51 #19
Цитата Сообщение от Darker
происходит конкатенация старого буфера с темповым массивом toString = buffer & Join(tempArray, "")
Дык оно так и должно работать.. разве нет? как же в строку собирать данные?
Выигрыш StringBufferа в том, что Join временного массива делается быстрее, чем последовательные конкатенации. Т.о. количество конкатенаций сильно уменьшается, но они всё равно есть для сборки строки.. по другому как слить данные в строку?



Цитата Сообщение от Darker
я с таким сталкивался когда подписывал вложения
тогда почему Ваш класс заваливается с ошибкой 14 (Out of String space), а если её забить, то вываливается в Overflow?
Вот пример вызова (только в pathname запишите путь к большому файлу):
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Код</div></div><div class="sp-body"><div class="sp-content">

Код
Dim session As New NotesSession
Dim stream As NotesStream
Dim pathname As String
Dim startTime As Single
Dim i As Long

Set stream = session.CreateStream

pathname = ""       Здесь я тестил на файлах 53 и 110 Mb

If Not stream.Open(pathname) Then
Messagebox pathname,, "Open failed"
Exit Sub
End If
fContent$ = stream.ReadText()
stream.Close

Dim ps As New PROTOTYPE_STRING

startTime = Timer()
For i = 1 To 7
Print i
ps.Add(fContent$)
Next
v = ps.Value()
Print "Final PROTOTYPE_STRING: Time = " & (Timer() - startTime) & " sec."
Добавлено:


Цитата Сообщение от Darker
Получается в конце StringBuffer нам выдаст ааааааааааааа......аа, а традиционный способ лишь аааааааааа,
Как-то нечестно получается
Потому что между Forами (между For и вызовом функции) стоит s = "".
0
mvyush
0 / 0 / 0
Регистрация: 19.04.2009
Сообщений: 2,219
13.10.2010, 15:14 #20
Цитата Сообщение от VladSh
Потому что между Forами (между For и вызовом функции) стоит s = "".
StringBuffer тоже сбрасывал:


Цитата Сообщение от nvy
Я внутренний цикл оформлял функцией. И StringBuffer и конкатенация собирали "аааааааааа", но много раз.
0
13.10.2010, 15:14
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.10.2010, 15:14
Привет! Вот еще темы с решениями:

Вопросы по курсовой работе
Привет всем. Создал эту тему, чтобы задавать вопросы по ходу дела. Что-то я...

Вопросы по созданию класса для работы сo строками
Всем привет, мне дано вот такое задание,не могу понять во 2 пункте про...

Excel: Вопросы по работе с формами
Есть ли 'живой' пример по работе с формами, а именно: - При открытии книги...

Общие вопросы по работе с COM-портом
У меня Win7. На системе классический встроенный последовательный порт и Usb...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru