ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: doitbest

[原创] 通过一题十解谈拓宽编程思路

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2013-4-4 14:42 | 显示全部楼层
本帖已被收录到知识树中,索引项:数据类型和基本语句
yjh_27 发表于 2013-3-28 20:39
第12种解法

对15楼 yjh_27 代码的一些改进:
  1. Sub Macro13() 'yjh_27 算法改进 by kagawa
  2.     Dim i&, j&, k&, m&, n&
  3.     m = Range("A65536").End(3).Row
  4.     arr = Range("A2").Resize(m, 2) '这里比实际数据多取1行,以后可以省去一层判断
  5.     n = Application.max(Range("A2").Resize(m))
  6.     '取巧,用工作表Max函数得到A列中【组的最大值】,本例=4。这样做就有通用性了。
  7.     '以后每组5个、6个……10个都可以处理,不需要改代码了。

  8.     ReDim brr(1 To m / 2 * (n + 1), 1 To 3) '这里/2处理是为了定义数组不要太浪费内存。
  9.     i = 1
  10.     Do
  11.         For j = 1 To n
  12.             k = k + 1
  13.             brr(k, 1) = j
  14.             '改进1: 在这里省略了If n <= UBound(arr) Then的判断
  15.             If arr(i, 1) = j Then
  16.                 brr(k, 2) = arr(i, 2)
  17.                 brr(k, 3) = i + 1   '列号
  18.                 i = i + 1
  19.             End If
  20.         Next
  21.         If i = m Then Exit Do
  22.         k = k + 1
  23.     Loop
  24. '    [d:f] = ""
  25.     Range("D2").Resize(k, 3) = brr
  26. End Sub
复制代码
因为减少了一层判断,所以速度可以提高一些。

TA的精华主题

TA的得分主题

发表于 2013-4-4 14:51 | 显示全部楼层
本帖最后由 香川群子 于 2013-4-4 14:53 编辑

我的数组算法-1:

第一循环,整理数据arr到数组brr
格式如下:
列号    0  1  2 ……
行1     1      1 ……
行2     2  2  2 ……
行3     3  3  3 ……
行4         4    ……
行5      ……    ……
……

即,把原始数据横向展开。

这样,根据整理结果自然地得到【组的最大值】=brr有效行数,以及【实际组数】=brr有效列数。
第二循环再把brr结果转换为需要输出的纵向数组crr
  1. Sub kagawa1()
  2.     Dim i&, j&, k&, m&, n&, r&, c&
  3.     m = Range("A65536").End(3).Row - 1
  4.     arr = Range("A2").Resize(m, 2)

  5.     ReDim brr(m / 2, m)
  6.     For i = 1 To m
  7.         If arr(i, 1) < r Then c = c + 1
  8.         r = arr(i, 1): If r > n Then n = r
  9.         brr(r, c) = arr(i, 2)
  10.     Next

  11.     ReDim crr(1 To (n + 1) * (c + 1), 1 To 2)
  12.     For j = 0 To c
  13.         k = k + 1
  14.         For i = 1 To n
  15.             k = k + 1
  16.             crr(k, 1) = i
  17.             crr(k, 2) = brr(i, j)
  18.         Next
  19.     Next
  20. '    [d:e] = ""
  21.      Range("D1").Resize(k, 2) = crr
  22. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2013-4-4 14:57 | 显示全部楼层
下面是直接一层循环就把结果整理到数组brr然后直接输出的代码。

由于过程中会出现3种不同的类型,所以看上去代码稍显复杂。
但运行效率相当不错。
  1. Sub kagawa2()
  2.     Dim i&, j&, k&, m&, n&, r&, t&
  3.     m = Range("A65536").End(3).Row - 1
  4.     arr = Range("A2").Resize(m, 2)
  5.     n = Application.max(Range("A2").Resize(m))
  6.    
  7.     ReDim brr(m / 2 * n, 1)
  8.     r = 1: k = 1
  9.     For i = 1 To m
  10.         t = arr(i, 1)
  11.         If t > r Then
  12.             For j = r To t - 1
  13.                 brr(k, 0) = j
  14.                 k = k + 1
  15.             Next
  16.         ElseIf t < r Then
  17.             For j = r To n
  18.                 brr(k, 0) = j
  19.                 k = k + 1
  20.             Next
  21.             k = k + 1
  22.             For j = 1 To t - 1
  23.                 brr(k, 0) = j
  24.                 k = k + 1
  25.             Next
  26.         End If
  27.         brr(k, 0) = t
  28.         brr(k, 1) = arr(i, 2)
  29.         k = k + 1
  30.         r = t + 1
  31.     Next
  32.     For j = r To n
  33.         brr(k, 0) = j
  34.         k = k + 1
  35.     Next
  36. '    [d:e] = ""
  37.      Range("D1").Resize(k, 2) = brr
  38. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2013-4-4 14:59 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 香川群子 于 2013-4-4 15:01 编辑

上传附件。到目前为止有12种代码 加上我的3个(其中一个是对15楼 yjh_27 的算法改进)

因此一共是13种代码了。

如果以速度考量,那么前面10种代码都没啥优势。呵呵。

一题十解2.rar

30.17 KB, 下载次数: 74

TA的精华主题

TA的得分主题

发表于 2013-4-4 15:27 | 显示全部楼层
香川群子 发表于 2013-4-4 14:59
上传附件。到目前为止有12种代码 加上我的3个(其中一个是对15楼 yjh_27 的算法改进)

因此一共是13种代码 ...

代码2本来没有BUG的,被你这么一改还改出BUG来了~

TA的精华主题

TA的得分主题

发表于 2013-4-4 17:01 | 显示全部楼层
我就喜欢这种 doitbest 和香川群子 高水平选手

在代码正确性的前提下,追求代码的通用性和效率

水平差点的能正确运行凑合一下过渡一下也行,到达一定水平了,应该另有追求

TA的精华主题

TA的得分主题

发表于 2013-4-4 20:48 | 显示全部楼层
本帖最后由 香川群子 于 2013-4-4 20:58 编辑
时光鸟 发表于 2013-4-4 15:27
代码2本来没有BUG的,被你这么一改还改出BUG来了~


应该没有bug 不过是我把清空结果区域的那一句代码注释掉了……因为比较速度时这一句代码比较耗时。

所以直接输出结果时看上去像是有错误而已。其实没有错误。

TA的精华主题

TA的得分主题

发表于 2013-4-4 20:58 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
香川群子 发表于 2013-4-4 20:48
应该没有bug 不过是我把清空结果区域的那一句代码注释掉了……因为比较速度时这一句代码比较耗时。

所 ...
  1. '      If v1 < maxNum And i > 2 Then
  2.            If v1 < maxNum Then
复制代码
  1.   '       If i > 2 Then k = k + 1
  2.            k = k + 1
复制代码
我说的是这两个地方,不能去掉对 i>2 的判断~

TA的精华主题

TA的得分主题

发表于 2013-4-4 21:05 | 显示全部楼层
时光鸟 发表于 2013-4-4 20:58
我说的是这两个地方,不能不去掉对 i>2 的判断~

哦。这里我是想试一试,去掉这个判断对速度有多大影响。……

因为楼主附件例子ID是从1开始的,这样改对结果不会有影响……。

…………

不过,如果附件数据有变化的话,10个代码中其它几个本身就会运行得到错误的结果……

比如说,把A2的ID改成从2开始(原来是从1开始)
那么,P1、P4和P7运行结果都是错误的。
而P9和P10直接就无法运行了。
……
所以我就不考虑这个问题了。
在大家一样的基础上比较就行了。

TA的精华主题

TA的得分主题

发表于 2013-4-4 21:11 | 显示全部楼层
时光鸟 发表于 2013-4-4 20:58
我说的是这两个地方,不能去掉对 i>2 的判断~

P2代码是你的出品么……呵呵。

为啥用: maxNum = Application.max(maxNum, arrPre(i, 1)) 来求最大值,
直接用 If arrPre(i, 1)>maxNum Then maxNum = arrPre(i, 1) 不是更简明么。

难道在VBA中使用工作表Max()函数有额外的好处?
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-5-20 11:31 , Processed in 0.041557 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

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