Сортировка документов коллекции

  • Автор темы LuMee
  • Дата начала

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 980
611
BIT
427
че-то мне кажется, что кусочек не полный :)
во всяком случае, я не разобрался полностью, да и яву я не очень хорошо знаю...
но, задача не массив отсортировать, а документы из коллекции (либо массива) выстроить в то положение, в котором они в виде отображаются...
сори, если я не правильно понял :)
коротко там используются класс HashMap, каждый член кот. хранит инфу необходимую для отображения
ключом является строка (например ключ вида)

далее по коду - получение ключа и вызов статич. метода для его сортировки

последнее - перебор коллекции (ключ уже отсортирован) и получение данных по хешу

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

в джава есть класс, кот. сортирует сразу... , но там свои оверхэды

вобщем, по коллекциям, здесь есть:

ЗЫ: LS крайне неэффективен, при реализации обработки строк (сравнение, копирование, поиск...)
 
30.05.2006
1 345
12
BIT
0
Medevic сказал(а):
метода qsort в Лотусе не реализовано
А знаете почему?
Потому что NotesDocumentCollection - это не абстракция в памяти, а настоящий серверный объект.
Методы класса NotesDocumentCollection не лопатят списки в памяти, а каждый раз обращаются к серверу.
К стати у сервера НЕТ команды collection.GetNthDocument(N), этот метод реализован чистА программно, как
Код:
set doc = collection.GetFirstDocument
For i=1 to N
set doc = collection.GetNextDocument(doc)
Next
Теперь оцените эффективность юзерского кода:
Код:
set collection = ...
For i=1 to collection.Count
set doc = collection.GetNthDocument(i)
..
Next
:)
 

Medevic

Что это ? :)
Green Team
10.12.2004
3 334
1
BIT
6
Ну в принципе ничто не мешало приделать к нему сортировку. Медленно, но работало бы.
Кстати, кидать коллекцию в массив не очень хорошая идея. Лучше кинуть туда notesId или UNID. И дергать документ при необходимости. А еще лучше сделать свой класс/тип, и запихнуть в массив этого класса/типа только необходимые данные из полей. И быстродействие хорошее, и памяти жрет мало. Ведь кому нужна отсортированная коллекция, что с ней делать? Нужны только отсортированные данные.
 
A

Akupaka

Потому что NotesDocumentCollection - это не абстракция в памяти, а настоящий серверный объект.
очень интересно... а это проверено, т.е. исследование в использовании памяти было? или я не понял утверждения...
т.е. сама коллекция - объект находящийся в локальной памяти, а если уже тянуть документ, то он тянется с сервера...
но мне кажется, что тут вполне возможно какое-то кеширование... хотя кто знает B)

а на счет уровня "оптимизации" collection.GetNthDocument(i) это известненько, где-то на IBM была хорошая статья на этот счет...
 
O

Omh

Если надо отосртировать коллекцию размером > integer массив не годится...
 
A

Akupaka

Если надо отосртировать коллекцию размером > integer массив не годится...
а два?! B))


я бы посоветовал, для того чтобы сделать себе хорошие алгоритмы сортировок и т.п., открыть старые добрые книжечки Кнута, изучить мат.часть и натворить... либо достать имеющееся... бо средствами лотуса каждый раз придется выделывать фокусы... (
 
30.05.2006
1 345
12
BIT
0
очень интересно... а это проверено, т.е. исследование в использовании памяти было? или я не понял утверждения...
Коллекция - объект (IDTable), находящийся в памяти (или на диске?) СЕРВЕРА. Клиент (впрочем, как и локальное приложение), в момент создания коллекции получает в зубы Хэндл (четырёхбайтовое целое) и в дальнейшем манипулирует коллекцией только через него. Полная аналогия с юниксовыми файлами:
Код:
f := Open(path);
Read(f, buffer);
...
пседокод
Код:
c := CreateCollection(db, searchRequest);
d := GetFirstDocument(c)
..
v := GetItemValue(d, "MyField")
GetNextDocument(с,d)
..
 
A

Akupaka

т.е. получается, что мы работаем с объектом коллекции как бы по технологии CORBA?..
я думал, что объект содержится в памяти клиента... в общем, мутновато пока что для меня, т.е. не очень верится, что все так запущено... B)
 
30.05.2006
1 345
12
BIT
0
я думал, что объект содержится в памяти клиента... в общем, мутновато пока что для меня, т.е. не очень верится, что все так запущено... ;)
Что тебя смущает?
Когда нормальная промышленная СУБД, такая как Oracle или DB/2, выполняет SQL-запрос, ты думаешь клиентское приложение перебирает все рекорды базы? Это только Clipper с DBF так работает.
Нет, ты знаешь, что "запрос выполняет сервер". А как он возвращает результат, если клиент - это DOS-приложение на машинке с 640К памяти а результат запроса - 1.5 миллиона записей? Всё в память качает?? Бредятина..
Разумеется, там всё просто и мудро: сервер создает у себя в уме объект, который называется "курсор". В общем, тот-же файл-хендл

А чем Notes хуже? ;)
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
еще можно отсортировать в представлении, а данные из представления вывести, исп NotesViewEntryCollection
ну а по правильному данные загружать в класс и в момент загрузки правильно их расставлять :D
 
T

TIA

1. функция CollectionToArray, которая тупо перегоняет NotesDocumentCollection в массив документов:

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

Лучше сделать либо получение Notes-документа экземпляром класса Comparer, либо перегнать ключи для сравнения из документов в объекты-посредники и сортировать уже их. Каждый посредник научить ещё получать соответствующий ему документ.

И ещё. Является ли массив массивом объектов или скаляров, для определения, использовать ли оператор "Set" или "Let", гораздо проще через оператор IsObject. Примерно так:

Код:
 Private Function IsArrayOfObjects(array As Variant) As Integer
if IsArray(array) then
if IsObject(array(0))
IsArrayOfObjects = True
EndIf
EndIf
End Function

array в данном случае не должен быть не инициализированным динамическим массивом
 
N

nvyush

SortCollection
Мне очень понравилось
С помощью этой библиотеки можно отсортировать коллекцию документов по значению любого поля документа
Ссылка на notes.net:
Там полное описание библиотеки, включая пример использования
notesDocumentCollection.IsSorted
Read-only. Indicates whether the documents in a collection are sorted. A collection is sorted only when it results from a full-text search of a database.

Делаем служебное представление с нужными сортировками и берём GetAllEntriesByKey.
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
231
На заре юности, как только пришёл в... Лотус, так тоже писал кучу функций по сортировке массивов, перегонка списков в массивы и обратно... аж страшно вспомнить. В итоге всё повыбрасывал, т.е. это бр..скриптогенерирование было это от недостатка знания архитектуры.
Обычные текстовые значения сортируются с помощью @Sort, а документы с помощью отстройки нужных видов и получением коллекции энтрисов или проходом с помощью навигатора; вообще при правильном проектировании системы даже такие случаи сводятся к минимуму.
 
D

Darker

В продолжение темы решил выложить свой вариант, который по "идее" схож с классом Medevic.
Используется QuickSort. Реализована возможность сборки необходимой информации во время единственного обхода исходной коллекции.
<!--shcode--><pre><code class='ls'>Public Const CONST_ASCENDING=True
Public Const CONST_DESCENDING=False
Private db As NotesDatabase

'########### FieldContainer - класс поля MirrorDoc ##############################
' Value- массив значений поля

Public Class FieldContainer
Public Value() As String
Private i As Integer

Sub New
Me.i=0
End Sub

Sub Delete
Erase Me.Value
End Sub

'Добавления значения поля _________________________________________________
Public Sub AddValue(Value As String)
On Error Goto eh
Redim Preserve Me.Value(Me.i) As String
Me.Value(Me.i)=Value
Me.i=Me.i+1
ex: Exit Sub
eh: Msgbox Error + " in " + Cstr(Getthreadinfo(1))+"(FieldContainer class) on line " + Cstr(Erl)
Resume ex
End Sub
End Class

'########### MirrorDoc - вспомогательный класс ##############################
' Хранит в себе сортируемые значения полей документа в коллекции,
' а также значения полей документа для дальнейшего использования

'sortField() - ключи сортировки
'sortFieldValue - составной ключ сортировки
'field - список полей для дальнейшего использования
'UNID - UniversalId документа

Public Class MirrorDoc
Private sortField() As String
Public sortFieldValue As String
Public field List As FieldContainer
Private ID As String
Private i As Integer

Sub New(ID As String)
Me.i=0
Me.ID=ID
End Sub

Sub Delete
Erase Me.sortField
Erase Me.field
End Sub

Public Function Document As NotesDocument
On Error 4091Goto eh
Set Document=db.GetDocumentByID(Me.ID)
ex: Exit Function
eh: Set Document=Nothing
Resume ex
End Function

'Добавления значения поля(ключа сортировки)______________________________
Public Sub AddSortField(sortFieldValue As Variant)
On Error Goto eh
Dim temp As String
If Isnumeric(sortFieldValue) Then
temp=Cstr(Format(sortFieldValue, "yyyy/mm/dd : hh/nn/ss"))
Else
temp=sortFieldValue
End If
Redim Preserve Me.sortField(Me.i) As String
Me.sortField(Me.i)=temp
Me.i=Me.i+1
ex: Exit Sub
eh: Msgbox Error + " in " + Cstr(Getthreadinfo(1))+"(MirrorDoc class) on line " + Cstr(Erl)
Resume ex
End Sub

'Добавления поля со значением, для дальнейшего использования__________________
Public Sub AddFieldValue(fieldName As String, fieldValue As Variant)
On Error Goto eh
If Not Iselement(Me.field(fieldName)) Then Set Me.field(fieldName)=New FieldContainer
If Isarray(fieldValue) Then
Forall fv In fieldValue
Call Me.field(fieldName).AddValue(Cstr(fv))
End Forall
Else
Call Me.field(fieldName).AddValue(Cstr(fieldValue))
End If
ex: Exit Sub
eh: Msgbox Error + " in " + Cstr(Getthreadinfo(1))+"(MirrorDoc class) on line " + Cstr(Erl)
Resume ex
End Sub

'Сборка составного ключа________________________________________________
Public Sub FinalizeSortFields
Me.sortFieldValue=Join(Me.sortField)
End Sub
End Class

'############### PROTOTYPE_SORT - главный класс сортировки ########################
' Сортирует по ключам список вспомогательных объектов(СВО),
' при необходимости возвращает отсортированную коллекцию документов, получая их по UniversalId
' Также возвращает сам СВО, с используемыми в дальнейшем значениями указанных полей

' bufferDoc - Сортируемый СВО
' sortMode - порядок сортировки

Public Class PROTOTYPE_SORT
Public bufferDoc List As MirrorDoc
Private sortMode As Boolean

Sub New
Dim s As New NotesSession
Set db=s.CurrentDatabase
End Sub

Sub Delete
Call Truncate()
End Sub

' Очистка СВО___________________________________________________________________
Private Sub Truncate
Erase Me.bufferDoc
End Sub

' Сортировка___________________________________________________________________
'col - входная коллекция
'keyToSort() - массив ключей(название полей) для сортировки
'sortMode - порядок сортировки
'keyToBuffer - поля документа, значения которых необходимо поместить в вспомогательный объект

Public Sub Sort(col As NotesDocumentCollection, keyToSort() As String, sortMode As Boolean, keyToBuffer() As String)
On Error Goto eh
Call Truncate()

Dim doc As NotesDocument
Dim i As Long, maxCount As Long
Dim IsBufferUsed As Boolean 'не возвращать коллекцию документов

Me.sortMode=sortMode
maxCount=col.Count
If maxCount=0 Then Goto ex

If Not Isarray(keyToSort) Then Msgbox "Нет ключей для сортировки!" : Goto ex
If keyToSort(0)="" Then Msgbox "Нет ключей для сортировки!" : Goto ex

If Isarray(keyToBuffer) Then
IsBufferUsed=Not(keyToBuffer(0)="")
Else
IsBufferUsed=False
End If

Set doc=col.GetFirstDocument
For i=1 To maxCount
Set Me.bufferDoc(i)=New MirrorDoc(doc.NoteID)

Forall kts In keyToSort
Call Me.bufferDoc(i).AddSortField(doc.GetItemValue(kts)(0))
End Forall
Call Me.bufferDoc(i).FinalizeSortFields

If IsBufferUsed Then
Forall ktb In keyToBuffer
Call Me.bufferDoc(i).AddFieldValue(ktb, doc.GetItemValue(ktb))
End Forall
End If
Set doc=col.GetNextDocument(doc)
Next

Set doc=Nothing
Set col=Nothing

If Not QuickSort(1, maxCount) Then Msgbox "Не удалось произвести сортировку!"

ex: Exit Sub
eh: Msgbox Error + " in " + Cstr(Getthreadinfo(1))+"(PROTOTYPE_SORT class) on line " + Cstr(Erl)
Resume ex
End Sub

'Быстрая сортировка(QuickSort итерационный вариант)______________________________________________________
'http://www.codeproject.com/KB/recipes/IterativeQuickSort.aspx
'By Pete Goodsall 25 Jan 2008
Private Function QuickSort(nFirst As Long, nLast As Long) As Boolean
QuickSort=False
On Error Goto eh
Dim i As Long, j As Long, nStkPtr As Long, nStackMax As Long
Dim nTmp As MirrorDoc
Dim bSortCompleted As Boolean, bDirection As Boolean
bSortCompleted=False
bDirection=True
nStackMax=(Log(nLast)+3)*2
Dim nStack() As Long
Redim nStack(nStackMax,2) As Long
Do
Do
i=nFirst
j=nLast
bDirection=True
Do
If compare(Me.bufferDoc(i).sortFieldValue, Me.bufferDoc(j).sortFieldValue) Then
Set nTmp=Me.bufferDoc(i)
Set Me.bufferDoc(i)=Me.bufferDoc(j)
Set Me.bufferDoc(j)=nTmp
bDirection=Not bDirection
End If
If bDirection Then j=j-1 Else i=i+1
Loop While(i<j)
If i+1<nLast Then
nStkPtr=nStkPtr+1
nStack(nStkPtr,0)=i+1
nStack(nStkPtr,1)=nLast
End If
nLast=i-1
Loop While(nFirst<nLast)
If nStkPtr=0 Then
bSortCompleted=True
Else
nFirst=nStack(nStkPtr,0)
nLast=nStack(nStkPtr,1)
nStkPtr=nStkPtr-1
End If
Loop While(Not bSortCompleted)
QuickSort=True
ex: Exit Function
eh: Msgbox Error + " in " + Cstr(Getthreadinfo(1))+"(PROTOTYPE_SORT class) on line " + Cstr(Erl)
Resume ex
End Function

'Сравнение двух значений___________________________________
Private Function Compare(value1 As String, value2 As String) As Boolean
If Me.sortMode Then 'По возрастанию
Compare=Strcompare(value1, value2)>0
Else 'По убыванию
Compare=Strcompare(value2, value1)>0
End If
End Function
End Class[/CODE]
<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"><!--shcode--><pre><code class='ls'> Dim s As New NotesSession
Dim col As NotesDocumentCollection
Dim doc As NotesDocument
Dim PS_S As New PROTOTYPE_SORT
Dim key(0) As String
Dim buf(0) As String

Set col=s.CurrentDatabase.AllDocuments
key(0)="ReportNumber"

'buf-должен быть пустым, иначе нам вернет пустую коллекцию
Call PS_S.Sort(col,key, CONST_ASCENDING, buf)
fileNum% = Freefile()
Open "c:\1.txt" For Output As fileNum%

Forall p In PS_S.bufferDoc
set doc=p.Document
Print #fileNum%, doc.ReportNumber(0)+" "+doc.RunUser(0)
End Forall[/CODE]
<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"><!--shcode--><pre><code class='ls'> Dim s As New NotesSession
Dim col As NotesDocumentCollection
Dim doc As NotesDocument
Dim PS_S As New PROTOTYPE_SORT
Dim key(0) As String
Dim buf(1) As String

Set col=s.CurrentDatabase.AllDocuments
key(0)="ReportNumber"
buf(0)="RunUser"
buf(1)="ReportNumber"
Call PS_S.Sort(col,key, CONST_ASCENDING, buf)

fileNum% = Freefile()
Open "c:\1.txt" For Output As fileNum%
Forall p In PS_S.bufferDoc
Print #fileNum%, p.field("ReportNumber").Value(0)+" "+p.field("RunUser").Value(0)
End Forall[/CODE]
 
Мы в соцсетях:

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