Страницы: 1 2 След.
RSS
Методы извлечения уникальных - Exists и Item (Dictionary)
 
Добрый день.  
При обработке огромной базы (нужно было извлеч уникальные) пользовался методом:  
If Not .exists(TekElem) Then .Add TekElem, TekElem ,  
поэксперементировав, обнаружил что есть еще метод вида:    
.Item(TekElem) = TekElem ,  
который на 100 000 целых чисел дает прирост в скорости аж 37 %.  
Выкладываю файлик в котором проведено тестирование обоих методов, может кому понадобится!  
И на всякий случай вопрос знатокам: нет ли каких то подводных камней в методе с использованием Item? Может я его не правильно применил?
Редко но метко ...
 
да, свойство item оказывается быстрее метода add..  
 
хотя add можно использовать и по-другому, но все равно он чуть-чуть медленнее
Живи и дай жить..
 
Тоже пробовал напрямую добавлять и тот же результат :)  
 
слэн, а что означает "0&"?
<FONT COLOR="CadetBlue">
 
насколько я знаю запись типа "0&" явно указывает компилятору что это число as Long, что бы он не терял время на определение типа числа. вот.
Редко но метко ...
 
Я не про знак, а в целом, что это такое и почему именно в таком виде? :)
<FONT COLOR="CadetBlue">
 
попробуйте прогнать код:  
 
Sub еее()  
   Dim x  
   x = 0&  
End Sub  
 
с этим знаком и без него.. - внимательно наблюдайте в locals
Живи и дай жить..
 
Прогнал: со знаком лонг, без оного интеджер, а как это влияет на выполнение макроса (который вы дописали) ?
Редко но метко ...
 
слэн, спасибо Вам! Кажется понял :)  
 
1. Если "x = 0&" - значение "Empty" (Variant/Empty)  
2. Если "x = 0"  - значение 0 (Variant/Integer)  
 
слэн, в Вашем варианте в словаре не задаем ключь, правильно?
<FONT COLOR="CadetBlue">
 
нет, наоборот, если требуется только подсчитать уникальные, то зачем их заносить в словарь?  
 
можно только ключ создавать.. но это мелочь.  
 
хотя ради истины лучше было бы так:  
Private Sub Dict_add()  
 
Dim TekElem As Long  
 
With CreateObject("Scripting.Dictionary")  
   StartTime = GetTickCount 'запоминаем начальное время  
   On Error Resume Next  
     
   For i = 1 To ColElemArr  
       .Add MyArr(i), TekElem  
   Next i  
   ColUnik = .Count  
   TotalTime = GetTickCount - StartTime 'вычисляем затраченное время  
End With  
 
End Sub
Живи и дай жить..
 
{quote}{login=GIG_ant}{date=24.03.2011 12:41}{thema=Re: }{post}Прогнал: со знаком лонг, без оного интеджер, а как это влияет на выполнение макроса (который вы дописали) ?{/post}{/quote}  
long обрабатывается быстрее..  
 
32битная архитектура заточена под  работу с 32 битами, составляющими тип long
Живи и дай жить..
 
понятно, спасибо.
Редко но метко ...
 
Добавить пару КЛЮЧ-ЗНАЧЕНИЕ в словарь можно такими способами:  
1 — метод .Add(<Key>,<Item>) - всем известен, но может вызывать ошибку если пара с таким ключом уже существует. Поэтому для выборки уникальных приходится усложнять код либо обработчиком ошибок, либо проверкой на .Exists(<Key>)  
 
2 — чтением по ключу: хх=.Item(<Key>)  
Если <Key>  в словаре есть, то возвращается ассоциированное с ним ЗНАЧЕНИЕ.  
Если <Key> в словаре отсутствует, то создается новая пара с КЛЮЧОМ=<Key> и ЗНАЧЕНИЕМ=Empty, возвращается хх=Empty  
 
3 — записью ЗНАЧЕНИЯ по ключу: .Item(<Key>=хх  
Если <Key> в словаре есть, то ассоциированное с ним ЗНАЧЕНИЕ заменяется на ЗНАЧЕНИЕ=хх  
Если <Key> в словаре отсутствует, то создается новая пара с КЛЮЧОМ=<Key> и ЗНАЧЕНИЕМ=хх  
 
4 — Key Property - изменяет КЛЮЧ ЗАПИСИ в словаре: .Key(<Key>)=<NewKey>  
Если <Key> в словаре отсутствует, то создается новая ЗАПИСЬ с КЛЮЧОМ=<NewKey> и ЗНАЧЕНИЕМ=Empty  
 
Надо бы эти методы сравнить по быстродействию, да всё руки не доходят.  
 
Когда я осваивал работу со словарями, то по разным источникам накропал для себя файл с описанием объекта Dictionary и несколькими тестовыми макросами для работы с ними.  
Файл забросил на файлообменник min.us : http://min.us/mvjlbaF  
Тот же файл - в приложении. Посмотрите. Может, кому и пригодится.
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Слэн, а если вместо:  
 
TekElem = MyArr(i)  
.Item(TekElem) = TekElem  
 
писать так  
 
.Item(MyArr(i)) = MyArr(i)  
 
ошибки не будет? Просто с моей точки знения лишнее телодвижение передвать сперва значение массива в переменную, а потом подставлять эту переменную, когда можно сразу обрабатывать значение массива. Скорости это не приносит, просто короче запись на одну строку и без использования переменной.
 
Помоему использование переменной как раз и приносит скорость, так как в первом случае MyArr(i) вычисляется 1 раз, а во втором 2 раза.
Редко но метко ...
 
слэн,  
а чем отличается    
GetTickCount Lib "kernel32" ()  
от    
Timer() ?  
Только тем, что Timer As Single в секундах, а GetTickCount As Long и в миллисекундах?
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
{quote}{login=Alex_ST}{date=25.03.2011 09:28}{thema=}{post}слэн,  
а чем отличается ...  
Только тем, что Timer As Single в секундах, а GetTickCount As Long и в миллисекундах?{/post}{/quote} Не совсем так:  
In Microsoft Windows the Timer function returns fractional portions of a second.  
Т.е. тоже в дробных частях секунд. В Макинтоше в секундах.
Я сам - дурнее всякого примера! ...
 
Серёга, не понял...  
Я же так и написАл: Timer As Single, т.е., естественно, с дробной частью и, кстати, может давать значения и меньше 1 миллисекунды.  
Тогда как GetTickCount As Long даёт только ЦЕЛОЕ число миллисекунд.  
 
Т.е. я так понимаю, что использование GetTickCount As Long вместо Timer As Single - это просто "ловля блох" на разнице в скорости обработки переменных  As Single и As Long ?  
Ну, тогда, т.к. они не в цикле, а определяются считанное число раз за время выполнения кода, то разница времени обработки, дейисвительно составит некоторое количество наносекунд :-)
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
А ещё я только что обнаружил ошибочку в описаниях методах объекта "Scripting.Dictionary", имеющихся в и-нете и без проверки внесённую мною в свой файл-пример использования...  
Попробовал добавлять записи в словарь путём попытки переименовать несуществующий ключ ( метод .Key(<Key>)=<NewKey> ) и получил полный отлуп:    
"32811: Ошибка, определяемая приложением или объектом"  
Раньше не пробовал, принял на веру... Каюсь :-(
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Алексей, Вам и так надо сказать спасибо, за то что Вы все методы и свойства причесали в этом файле.Ну просто MSDN.  
 
Спасибо за файлик, добавил к себе в мануалы, так как иногда что то и забывается :)
Спасибо
 
Самое интересное, что, поискав в MSDN, я обнаружил там чёткое указание на то, что при попытке переименовать отсутствующий в словаре ключ создастся новая запись:  
"If key is not found when changing a key, a new key is created and its associated item is left empty." ( http://msdn.microsoft.com/en-us/library/1ex01tte%28v=VS.85%29.aspx )  
Ну, уж если MSDN теперь нельзя верить на слово, то куды же мы катимьси?
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Алексей попробуй у меня работает :)  
 
Sub test()  
Set Dict = CreateObject("Scripting.Dictionary")  
Dict.Add 1, "Раз"  
Dict.Add 2, "Два"  
Dict.Key(1) = "Три"  
MsgBox Dict.Item("Три")  
MsgBox Dict.Item(2)  
End Sub
Спасибо
 
Дмитрий,  
только, поработав со словарями, исходя из личного опыта я очень рекомендую использовать не сокращенную форму записи метода Add:  
oDict.Add "aaa", "bbb"  
а полную:  
oDict.Add  Key:="aaa", Item:="bbb"  
И это не украшательство для понимабельности.  
Просто у уже привычных многим коллекций по умолчанию сначала указывается Item, а потом уже Key : oColl.Add (Item, [Key] as String, [Before | After] as Long | String)
И поэтому получается такая путаница, что без залезания в справку (которая по словарям отсутствует) трудно при беглом разборе кода понять, что является ключом, а что значением в записях  
oDict.Add "aaa", "bbb"  
oColl.Add "aaa", "bbb"
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Спасибо, за совет, но останусь при своем!  :)    
так все же работает изменение ключа?
Спасибо
 
в первоначальном варианте myarr был типа вариант.. поэтому переприсваивание  
tekelem=myarr  давало прирост скорости, за счет того, что tekelem был типа long  
 
потом я переопределил myarr  в long и переприсваивание потеряло смысл..  
 
 
но он может опять появиться, если myarr придется брать с листа, а не получать вычислением..  
 
"серьезным" недостатком timer является его цикличность величиной в сутки.. - т.е. интервал более суток им не измерить..
Живи и дай жить..
 
Дмитрий,  
вы просто моментально наступили как раз на те грабли, о которых я предупреждал:  
Dict.Add 1, "Раз" - это аналог .Add key:=1, Item:="Раз"  
Dict.Add 2, "Два" - это аналог .Add key:=2, Item:="Два"  
поэтому действием:  
Dict.Key(1) = "Три"  
вы просто переназначаете СУЩЕСТВУЮЩИЙ ключ, а не добавляете новую запись.  
попробуйте вместо    
Dict.Key(1) = "Три"  
записать  
Dict.Key(33) = "Тридцать три"  
и получите "отлуп".
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Алексей, я уже понял, что "недочитал" про несуществующий ключ :)  
Спасибо
Спасибо
 
кому интересно хорошее описание,про словари и не только, приведено тут:  
 
http://www.script-coding.com/
Спасибо
 
Дмитрий,  
в моём самопальном файле-справочнике на каждой странице в первой строке - ссылки.  
В том числе и эта - ОЧЕНЬ КРУПНО - в ячейке А1 листа Dictionary(2)
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Народ!  
Кто-нибудь ещё тестаните, пожалуйста, код:  
Sub testAddToDict()  ' разные методы добавления записей в словарь  
  Dim xx  
  With CreateObject("Scripting.Dictionary")  
     .Add Key:=1, Item:="Раз"  ' обычный метод .Add  
     .Item(2) = "Два"   ' запись в словарь ЗНАЧЕНИЯ по отсутствующему ключу  
     xx = .Item(3)   ' чтение из словаря ЗНАЧЕНИЯ по отсутствующему ключу (вернёт xx = Empty)  
     '.Key(4) = 4   ' переназначение отсутствующего ключа - НЕ РАБОТАЕТ !!!  
Debug.Print "Key" & vbTab & "Item"  
     For xx = 1 To .Count  
Debug.Print xx & vbTab & vbTab & .Item(xx)  
     Next xx  
  End With  
End Sub  
Так должно всё пройти.  
А вот если снять комментарий со строки '.Key(4) = 4 , то у меня вылетает на ней с ошибкой: "32811: Ошибка, определяемая приложением или объектом".  
А то я уж, действительно, начал сомневаться, кто врёт: мой комп/офис или всё-таки MSDN - http://msdn.microsoft.com/en-us/library/1ex01tte%28v=VS.85%29.aspx
С уважением, Алексей (ИМХО: Excel-2003 - THE BEST!!!)
 
Так и есть - у меня тоже ошибка. И сейчас, и на примере R Dmitry - только в варианте "33" :)  
XL2000 Eng
Страницы: 1 2 След.
Читают тему
Наверх