Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 9026|回复: 13

[分享] 【烟花原创】VBA零基础之第124篇 字典(一)

[复制链接]
发表于 2014-3-13 09:58 | 显示全部楼层 |阅读模式
本帖最后由 hwc2ycy 于 2014-3-13 11:16 编辑

一、认识字典
说到字典,大家立即就会想到新华字典,成语字典,英汉字典,不过我们要谈的字典是VBA里的字典对象。经常在论坛做题的童鞋对字典可能有一种固有的印象:字典是用来去重复的。我刚做题那会接触字典时也感觉是那么回事,等接触多了,才发现去重复不过是一个小的功能。
我们在查字典时,总是根据某个关键字查到与之相关的内容,譬如英汉字典,查找时是根据英文单词查找对应的汉语解释。
字典对象也是如此,字典对象相当于一种联合数组,它是由具有唯一性的关键字(Key)和它的项(Item,也有叫条目,个人习惯,你怎么顺口就怎么叫联合组成。我们经常用的手机通讯录也有类似功能,姓名与电话对应。
当我们要从字典中检索某个Item时,就要知道与之相对应的关键字Key,这样就完成了一个数据检索功能,这与查找电话号码时输入名字进行查找是一样的。

二、如何创建字典
1.前期绑定
第一步 VBA工程中添加引用
VBE中,点击菜单 工具引用,在列表中找到Microsoft Scripting Runtime,勾选后 确定 即可。

1.png
这里在列表中查找时有个技巧,按m后可以直接跳转到列表中以M开头的引用。

如果在列表中还是找不到的话,就点击左下角的开始,运行
输入regsvr32 scrrun.dll
然后回车。
注意上面的命令中32与s之间有个英文空格。

VISTA/WIN7/WIN8用户可能需要以管理员方式运行。
2.jpg
然后再重新打开EXCEL试试。

或者
VBE中,点工具引用,在引用窗口中点击 浏览 ,输入scrrun.dll打开确定 即可。


上图中的打开对话框中默认路径是system32(XP),一般不需要改。

推荐用这种方法,来得更快,个人感觉在列表中找比较烦锁(当然前提是你得知道引用的DLL文件)。
第二步声明变量,创建对象实例。
dim d as dictionary
set d=new dictionary

2.后期创建
直接声明变量,然后通过createobject创建。
dim dic as object
setdic=createobject("scripting.dictionary")

前期引用与后期创建的区别         
1.前期速度快(这个没太感觉出来)
2.前期引用的在代码编辑时有自动成员列表,方便使用。
3.前期引用的KeysItems方法返回的数组可直接引用,不需要中间变量。

2,3点是很明显的,特别是第2点,妈妈再也不用担心我记不住字典了。

excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
发表于 2014-3-13 11:06 | 显示全部楼层
2,3点是很明显的,特别是第2点,妈妈再也不用担以我记不住字典了。

这里是不是有错别字

评分

参与人数 1金币 +1 收起 理由
hwc2ycy + 1 一字一BB。

查看全部评分

回复

使用道具 举报

发表于 2014-3-13 12:00 | 显示全部楼层
字典原理:

大量数据存储在数组中以后,我们要引用数组中的具体某个元素时,
必须知道其数组下标。

例如:
Dim arr(1 to 100)
For i = 1 to 100
   arr(i) = Int(Rnd*10000)
Next
以上生成了一个1 到 100 个元素的随机数 数组。

但是问题来了,如果我想知道,这个数组中有没有一个元素=100或88,该怎么办呢?

最简单可靠的方法是遍历检查:
t = 88 '待查找值
For i = 1 to Ubound(arr)
   If arr(i) = t Then Msgbox "找到了,是第 " & i & "个" : Exit For
Nex
If i > Ubound(arr) Then Msgbox "没有找到、不存在!"


…………
【如果数据量在几十到几千,即万以下数量级时,运算速度依然很快,毫无压力。】
但是如果数据量很大,并且需要反复遍历检查计算时,那么因为这个算法的效率是相当低的,
所以可能会导致 电脑运算假死机。

…………
另一个数据搜寻的经典方法,是【二分法查找】
但是这个方法算法效率提高很多,但仍有一个致命缺陷:
需要待插选数组中元素必须是已经排序处理过的。否则就会出错。


…………
因此,科学家、数学家想到了下面的算法原理:
【哈希散列表算法】简称【哈希算法】

方法如下:
对于每一个元素,对其进行一个算法固定的运算,得到一个整数值,作为存储到数组中的下标。
有如下要求:
1. 由于算法固定,因此同一个元素值总是 计算得到完全相同的【整数值】
   即相同的存储数组下标行位置。

2. 不同的元素值,必须保证得到不同的计算结果的【整数值】
   即不同的存储数组下标行位置。

3. 该存储数组的使用率比较高。


…………






回复

使用道具 举报

发表于 2014-3-13 13:10 | 显示全部楼层
关于散列算法的原理,有些类似于拉面操作。

3. 合适大小的数组

对于1-1000区间的1000个随机数,定义一个1000个元素大小的数组就好了。
而对于1-10万区间的1000个随机数,
如果定义一个10万个元素大小的数组当然可以,但数组里面到处都是空的,使用效率太低了。


散列算法的一个便于理解的思路就是:
对于1-10万区间的1000个随机数,定义一个5000个元素大小的数组,
然后,对于这1000个随机数,进行 Mod 5000求余运算,
那么首先:
1. 得到的余数一定是在0-4999之间
2. 如果这1000个随机值的求余运算结果都不相同,则已经保证唯一性了……

到这里就可以认为,求余运算可以达到把这1000个随机数打散以后分成一个不重复的唯一数列。

这就是我们设计字典时想要得到的。

…………
但是慢着,你不能保证1000个随机数的求余结果都一定是唯一的……如果正好有余数结果相同的不同值呢?

因此,就需要拉面算法了。

即,把这1000个随机数都扩大n倍,然后再求Mod 5000的余数……

你会发现,你一定能找到一个适当的n值,保证这1000个随机数t的 t*n mod m 是唯一不重复的值。

为便于理解,你可以这么去想象:
1. 在一根粗面条上有很多随机分布的芝麻点。(比喻为1000个随机数)
2. 把此面条对折以后、部分芝麻点会发生重叠 (部分随机数的mod求余结果相同)
于是反复进行下面的操作:
3. 把面条拉伸 (倍数扩大)
4. 拉伸后的面条对折 (求余运算)
5. 检查芝麻是否重叠 (保证求余运算结果的唯一性)

…………
呵呵,这个就是字典哈希散列算法的精髓了。




回复

使用道具 举报

发表于 2014-3-13 13:18 | 显示全部楼层
当然,实际算法要达到高效和实用,是有很多细节需要自动处理的。

并不是随便就可以做到的,但原理基本如此:
通过对元素值t对应唯一索引数值k扩大n倍,然后mod m求余的运算,
得到一个对应于m个元素数组的唯一下标值(地址)
相同的算法保证所有元素都能得到一个唯一地址。
相同的算法保证每一个相同元素都能得到相同的一个唯一地址。

以上,对字典原理做了一个非常简略的介绍。

这是很多能在VBA中熟练运用字典方法的中、高级坛友所不清楚的知识。

但对于更准确地理解字典算法的优缺点、还是很有意义的。



回复

使用道具 举报

发表于 2014-3-13 13:38 | 显示全部楼层
本帖最后由 香川群子 于 2014-3-13 13:52 编辑

Function haxi(txt, m, k)
    For i = 1 To Len(txt)
        s = (s + AscW(Mid(txt, i, 1)) * 2 ^ (i - 1) * k) Mod m
    Next
    haxi = s
End Function

以上自定义函数是哈希算法求余结果的模拟运算(但实际过程要复杂的多)

下面是根据上述自定义函数对下标元素的模拟计算和分布结果图例:

哈希算法.jpg

评分

参与人数 2 +15 收起 理由
759857387 + 3 赞一个!
冥王 + 12 字典原理的讲解,非常具有故事性、趣味性,.

查看全部评分

回复

使用道具 举报

发表于 2014-3-22 13:17 | 显示全部楼层
赞~下次不记得怎么设置就来这。
回复

使用道具 举报

发表于 2014-4-6 22:42 | 显示全部楼层
学习字典的前期绑定和后期绑定
回复

使用道具 举报

发表于 2014-4-9 18:29 | 显示全部楼层
字典原理的讲解,非常具有故事性、趣味性,便于记忆与理解
回复

使用道具 举报

发表于 2014-6-18 15:03 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-5-2 21:42 , Processed in 0.325895 second(s), 12 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表