标题: 【练习-052】根据原始数据进行相关统计操作 [打印本页]
作者: batman 时间: 2009-11-19 11:49 标题: 【练习-052】根据原始数据进行相关统计操作
出题目的:
综合考察会员的文本数据处理能力
加分原则:
满分30分,酌情加分,以思路为重
题目如下:
有一从excel(实际中是要对excel直接操作)导入的文本a.txt如下:- 部门 A项完成 B项完成 C项完成 D项完成 E项完成 F项完成 当天排名 当月累计排名
- 一分局 2 7 0 1 7 7 2 1
- 二分局 0 0 0 1 0 0 6 2
- 三分局 2 8 1 1 1 9 1 3
- 四分局 0 0 0 1 1 0 5 5
- 五分局 0 0 0 1 2 1 3 7
- 六分局 0 0 0 1 0 0 4 6
- 七分局 0 5 0 1 0 6 6 3
复制代码
要求对用批处理后生成统计文本b.txt,要求列出每项完成的总和,如有完成为0的局则
一一列出,没有则列出"无";将当日排名和当月排名按名次从小到大的顺序列出局名和名次
,请注意有排名相同的情况。- A项完成4,完成为0的局:二分局,四分局,五分局,六分局,七分局
- B项完成20,完成为0的局:二分局,四分局,五分局,六分局
- C项完成1,完成为0的局:一分局,二分局,四分局,五分局,六分局,七分局
- D项完成7,完成为0的局:无
- E项完成11,完成为0的局:二分局,六分局,七分局
- F项完成23,完成为0的局:二分局,四分局,六分局
- 当日排名:三分局1,一分局2,五分局3,六分局4,四分局5,二分局6,七分局6
- 当月累计排名:一分局1,二分局2,三分局3,七分局3,四分局5,六分局6,五分局7
复制代码
提示:分局数和项目数都是未知的
[ 本帖最后由 batman 于 2009-11-19 21:34 编辑 ]
作者: batman 时间: 2009-11-19 15:00
提示:批可以不用读取a.txt第一行,用一系列的变量来代替首行内容
作者: 523066680 时间: 2009-11-19 17:11
……打算看帖不答题……
作者: netbenton 时间: 2009-11-19 20:17
呵呵。。。
我也是这么想的 ^_^
作者: zqz0012005 时间: 2009-11-19 21:19
其实是两个不同的问题,而其中排序问题没必要放在这里,可以另外出题(好像出过?)
作者: batman 时间: 2009-11-19 21:22 标题: 回复 5楼 的帖子
这个排序真是不同于以往的排序,原因是你就是排出了名次的序,你还要考虑和分局关联,特别是出现同名次的情况下
作者: zqz0012005 时间: 2009-11-19 21:31
还是一样啊,只是把字符交换一下位置而已。
一分局 2 7 0 1 7 7 2 1
二分局 0 0 0 1 0 0 6 2
一分局 1
二分局 2
1一分局
2二分局
排好再交换回来
作者: batman 时间: 2009-11-19 21:39 标题: 回复 7楼 的帖子
楼上是不是搞错题意了,排名是用一定的公式算出来的,而不是由前面的完成情况来定的。。。
作者: zqz0012005 时间: 2009-11-19 21:40
“导入的文本a.txt如下”
后面两列数据是怎么来的?要根据什么公式?还是自己编算法?
[ 本帖最后由 zqz0012005 于 2009-11-19 21:43 编辑 ]
作者: batman 时间: 2009-11-19 21:43
直接读到的啊,排名肯定是有同名次的情况出现的,如当日排名:三分局1,一分局2,五分局3,六分局4,四分局5,二分局6,七分局6
作者: zqz0012005 时间: 2009-11-19 21:51
既然是直接读到的,那可能你没有明白我7楼的意思
::截取两列:
一分局 1
二分局 2
三分局 3
四分局 5
五分局 7
六分局 6
七分局 3
::交换:
...
作者: zqz0012005 时间: 2009-11-19 21:55
即使列数未确定,也很容易求得。
即使不求列数,只截取特定两列也容易。
作者: zqz0012005 时间: 2009-11-19 21:57
这个排序问题其实也不错:
以A3列的大小为主要排序,A2列的大小为次要排序,应该怎么实现?
http://bbs.verybat.org/viewthread.php?tid=17101
作者: batman 时间: 2009-11-19 21:57 标题: 回复 12楼 的帖子
我没说此题无解吧,晕,我只是一再在强调出现同名次的情况需要处理
作者: zqz0012005 时间: 2009-11-19 22:03 标题: 回复 14楼 的帖子
晕,我也没说此题无解,12楼只是对11楼的补充,同时都是对7楼的解释。
而且题目给的结果并未处理啊:
当月累计排名:一分局1,二分局2,三分局3,七分局3,四分局5,六分局6,五分局7
两个第三名后,直接是第五名,没有将名次序号调成4
作者: batman 时间: 2009-11-19 22:07 标题: 回复 15楼 的帖子
为什么要调成第四名,说了有并列名次出现的情况。。。
[ 本帖最后由 batman 于 2009-11-19 22:10 编辑 ]
作者: zqz0012005 时间: 2009-11-19 22:11 标题: 回复 16楼 的帖子
交换位置后:
0001 一分局
0002 二分局
0003 三分局
0005 四分局
0007 五分局
0006 六分局
0003 七分局
......
0123 一百五十分局
(前面的0是添加的,再截取后4位)
既然无需调整名次序号,那不就结了,直接sort
[ 本帖最后由 zqz0012005 于 2009-11-19 22:13 编辑 ]
作者: batman 时间: 2009-11-19 22:13 标题: 回复 17楼 的帖子
还请就此题给出完整代码
作者: zqz0012005 时间: 2009-11-19 23:26
达到要求的输出格式使得步骤多了点。
(显然,Ctrl+A可见)
- @echo off
- %1 %2
-
- setlocal enableDelayedExpansion
- set n=0
- for /f "tokens=1* delims==" %%a in ('"set /p head=<1.txt& set head"') do ^
- for %%i in (%%b) do set _!n!=%%i& set /a n+=1
- set /a items=n-3, day_ranking=n-1, month_ranking=n
- for /f "skip=1 delims=" %%a in (1.txt) do set m=0&for %%i in (%%a) do (
- if "!m!"=="0" set department=%%i
- for %%x in (_!m!) do (
- if "%%i"=="0" set %%x_0=!%%x_0! !department!
- set /a !%%x! += %%i
- )
- set /a m+=1
- set serial=0000%%i& set serial=!serial:~-4!
- if !m!==!day_ranking! set _day_ranking=!_day_ranking! !serial!.!department!
- if !m!==!month_ranking! set _month_ranking=!_month_ranking! !serial!.!department!
- )
- for /l %%a in (1 1 %items%) do (
- if "!_%%a_0!"=="" set _%%a_0= 无
- set #%%a=!_%%a! ^^!!_%%a!^^!, 完成为0的局:!_%%a_0!
- )
- for /f "tokens=1* delims==" %%a in ('set #') do echo %%b
-
- for /f "tokens=* delims=0" %%a in ('%~s0 goto sort_ "!_day_ranking!"^|sort') do set #day_ranking=!#day_ranking!,%%~xa%%~na
- for /f "tokens=* delims=0" %%a in ('%~s0 goto sort_ "!_month_ranking!"^|sort') do set #month_ranking=!#month_ranking!,%%~xa%%~na
- set #day_ranking=!#day_ranking:~1!
- set #month_ranking=!#month_ranking:~1!
- echo 当日排名: !#day_ranking:.=!
- echo 当月累计排名: !#month_ranking:.=!
-
- pause&exit/b
-
- :sort_
- for /f "delims=" %%a in ("%~3") do for %%i in (%%~a) do echo %%i
- goto :eof
复制代码
[ 本帖最后由 batman 于 2009-11-21 11:58 编辑 ]
作者: batman 时间: 2009-11-19 23:41
楼上的效率显然有问题。。。这就是用^|sort造成的
[ 本帖最后由 batman 于 2009-11-19 23:50 编辑 ]
作者: zqz0012005 时间: 2009-11-20 00:05
前面数据整理不怎么耗时,主要是不想用临时文件而将排序模块整合在一起造成的。
如果不担心分局数和项目数加起来会超过变量最大长度,两次排序其实可以goto一次完成,将_day_ranking和_month_ranking分别不同的前缀补位,然后拼接,goto时还可省略%3,排序后分开时再加判断。
作者: batman 时间: 2009-11-20 00:16 标题: 本人的解
- @echo off&setlocal enabledelayedexpansion
- for /f "delims=" %%a in (a.txt) do (
- set /a hang+=1,lie=0
- for %%b in (%%a) do (
- set /a lie+=1&set "str=%%b"
- if not defined fj if "!str:~,1!" equ "当" set /a fj=lie
- if !hang! equ 1 (
- if !lie! neq 1 set "_!lie!=%%b#:"
- ) else (
- if !lie! equ 1 (
- set "ju=%%b"
- ) else (
- for %%c in (!lie!) do (
- if %%c lss !fj! (
- set /a num_%%c+=%%b
- if !str! equ 0 set "_%%c=!_%%c!!ju!,"
- ) else (
- if not defined %%c_%%b (
- set "%%c_%%b=!ju!%%b,"
- ) else (
- set "%%c_%%b=!%%c_%%b!!ju!%%b,"
- )
- )
- )
- )
- )
- )
- )
- cd.>b.txt
- for /l %%a in (2,1,%lie%) do (
- set "str=!_%%a!"
- if %%a lss %fj% (
- for %%b in (!num_%%a!) do (
- if "!str:~-1!" neq ":" (
- set "str=!str:~,-1!"&echo !str:#=%%b,完成为0的局!>>b.txt
- ) else (
- echo !str:#=%%b,完成为0的局!无>>b.txt
- )
- )
- ) else (
- for /l %%b in (1,1,%hang%) do if defined %%a_%%b set "str=!str! !%%a_%%b!"
- set "str=!str:#=!"&echo !str:~,-1!>>b.txt
- )
- )
- start b.txt
复制代码
[ 本帖最后由 batman 于 2009-11-21 11:57 编辑 ]
作者: 523066680 时间: 2009-11-20 11:00
大概地模拟了一下2维数组,确实是一道“复合题”,后面的两行,我就不弄了- @echo off
- setlocal enabledelayedexpansion
- set /a a=-1
- for /f "tokens=*" %%a in (a.x) do (
- set /a a+=1,b=-1
- for %%b in (%%a) do (
- set /a b+=1
- set str[!a!][!b!]=%%b
- )
- )
- for /l %%b in (1,1,6) do (
- for /l %%a in (1,1,%a%) do (
- set /a !str[0][%%b]!+=str[%%a][%%b]
- if "!str[%%a][%%b]!"=="0" (set zero%%b=!zero%%b!!str[%%a][0]!;)
- )
- if "!zero%%b!"=="" (set "zero%%b=无;")
- for %%x in (!str[0][%%b]!) do (set now=!%%x!)
- echo,!str[0][%%b]!!now! , 本次完成0的分局: !zero%%b:~0,-1!
- )
-
- pause
- exit
复制代码
作者: batman 时间: 2009-11-20 11:45 标题: 回复 23楼 的帖子
后面的两行才是本题的重点哦。。。
作者: 523066680 时间: 2009-11-20 12:05
如果要算法来排序,可能会选择用选择排序吧。。。。。。
排序可是个出过的题。你们用set 变量名, 用冒泡,用选择,用希尔,然后呢?
作者: zqz0012005 时间: 2009-11-20 12:17
看了一下,排序的问题和帖子有不少
http://www.bathome.net/viewthread.php?tid=1336
http://www.bathome.net/viewthread.php?tid=1581
http://www.bathome.net/viewthread.php?tid=4819
http://www.bathome.net/viewthread.php?tid=4196&page=1#pid26902
[ 本帖最后由 zqz0012005 于 2009-11-20 12:32 编辑 ]
作者: batman 时间: 2009-11-20 13:16 标题: 回复 26楼 的帖子
我现在用的方法可不是排序哦,严格上来讲应属于变量赋值法。
作者: zqz0012005 时间: 2009-11-20 13:24
所谓的“偏方”,其实也是良方
http://www.bathome.net/viewthread.php?tid=1581&page=1#pid8439
[ 本帖最后由 zqz0012005 于 2009-11-20 13:25 编辑 ]
作者: 523066680 时间: 2009-11-20 14:07
还是做了- @echo off
- setlocal enabledelayedexpansion
- ::第一部分是赋值二维数组模型
- set /a a=-1
- for /f "tokens=*" %%a in (a.x) do (
- set /a a+=1,b=-1
- for %%b in (%%a) do (
- set /a b+=1
- set str[!a!][!b!]=%%b
- )
- )
- set /a 项目数=b-2
- ::给出某项任务完成的个数,并找出0的局
- for /l %%b in (1,1,%项目数%) do (
- for /l %%a in (1,1,%a%) do (
- set /a !str[0][%%b]!+=str[%%a][%%b]
- if "!str[%%a][%%b]!"=="0" (set zero%%b=!zero%%b!!str[%%a][0]!;)
- )
- if "!zero%%b!"=="" (set "zero%%b=无;")
- for %%x in (!str[0][%%b]!) do (set now=!%%x!)
- echo,!str[0][%%b]!!now! , 本次完成0的分局: !zero%%b:~0,-1!
- )
- ::最后两列,和对应的项目名按顺序,匹配好并列出
- set /a last=b-1
- :result
- set result=!str[0][%last%]!:
- for /l %%b in (1,1,%a%) do (
- for /l %%a in (1,1,%a%) do (
- if "!str[%%a][%last%]!"=="%%b" (
- set result=!result! !str[%%a][0]!!str[%%a][%last%]!
- )
- )
- )
- echo,%result%
- if %last% lss %b% (set /a last+=1 &goto :result)
- pause
- exit
复制代码
[ 本帖最后由 523066680 于 2009-11-20 14:49 编辑 ]
作者: batman 时间: 2009-11-20 14:50 标题: 回复 29楼 的帖子
针对此代码发表点个人意见,不当之处还请误解:
一、优点:
1、在批处理中引入数组概念,拓展了批的处理功能;
2、代码较简洁,这其实也是因为引入了数组,减少了累加赋值的过程;
3、书写较规范,但请注意a.x是不符合题意的。
二、不足之处:
1、因为代码是用数组变量表示的每个单元的值,所以变量用量较大,如达到百行百列时,变
量就要用到一万个,是对系统资源的考验;
2、出现6这个常量,这与题意中未知行未知列是不相符的;
3、代码中使用了goto循环,在效率上比for循环要低。
总之,exist这段代码还是表现出了其高水平的批处理技巧,值得大家学习。
作者: 523066680 时间: 2009-11-20 14:59
对出现的6进行了修补
数组赋值后遗留的 a b变量分别表示行和列
因为最后两列是排名,我用项目数=b-2表示项目数量,剔除了6
不足之处,表示同意。
[ 本帖最后由 523066680 于 2009-11-20 16:41 编辑 ]
作者: 523066680 时间: 2009-11-21 09:22 标题: 我也发表一点观点
事实上这道题会遇到的排序问题,根之前讨论的纯数字排序有一点不同
就是你要:给这个项目排序,不管你怎样操作,
最终都必须为每个数字匹配这个数值的"主人" 并显示出来。
这个问题在表格操作中是经常会遇到的,例如给学生各科成绩排名
此时要排的就不仅仅是数值,还有该分值对应的"主人"
针对于各列并且要关系到其中一项的行上其他数据时,我认为应该让批处理加入 二维数组 概念
[ 本帖最后由 523066680 于 2009-11-21 10:02 编辑 ]
作者: batman 时间: 2009-11-21 11:56
&&这个问题的确是我在工作中遇到和解决的,实际上的操作是用批先生成一个temp.vbs,
然后用temp.vbs读取指定工作表的指定分页(sheet*)的指定范围指定单元格的数据,然
后输入到temp.txt(这是用批做不到的),然后用批进行数据统计分析并输出最终想要的结
果。这是个实用性很强的问题,因为考虑难度比较大,所以在出题时省去了读取excel表数
据的步骤,直接给出了temp.txt的内容。所以请工作中与excel表打交道的会员都认真做一下
本题,不做也可以对照前面给出的代码仔细思考一下,说不定以后你就会遇到类似的问题。
作者: Seter 时间: 2009-11-21 19:36
-
- @echo off
- setlocal enabledelayedexpansion
- set/pt=<in.txt
- set t=!t: = !
- set max1=0
- set max2=0
- for %%i in (%t:~2,-11%) do (
- set/an+=1
- set n!n!=%%i
- )
- for /f "skip=1 tokens=1* delims= " %%i in (in.txt) do (
- set i=0
- for %%z in (%%j) do (
- set/ai+=1
- if !i! leq %n% (
- for %%y in (!i!) do (
- if %%z==0 (
- for %%x in (w!n%%y!) do (
- set %%x=!%%x!,%%i
- )
- ) else (
- set/as!n%%y!+=%%z
- )
- )
- ) else (
- if defined p (
- set p=
- set y%%z=!y%%z!,%%i%%z
- if !max2! lss %%z (
- set max2=%%z
- )
- ) else (
- set p=1
- set r%%z=!r%%z!,%%i%%z
- if !max1! lss %%z (
- set max1=%%z
- )
- )
- )
- )
- )
- for /l %%i in (1,1,%n%) do (
- set o=!n%%i!
- for %%x in (s!n%%i!) do (
- set o=!o!!%%x!,完成为0的局:
- if defined w!n%%i! (
- for %%x in (w!n%%i!) do (
- echo !o!!%%x:~1!
- )
- ) else (
- echo !o!无
- )
- )
- )
- set o=
- for /l %%i in (1,1,%max1%) do (
- set o=!o!!r%%i!
- )
- echo 当日排名:!o:~1!
- set o=
- for /l %%i in (1,1,%max2%) do (
- set o=!o!!y%%i!
- )
- echo 当月累计排名:!o:~1!
- pause>nul
复制代码
[ 本帖最后由 Seter 于 2009-11-21 21:42 编辑 ]
作者: batman 时间: 2009-11-21 20:51 标题: 回复 34楼 的帖子
输出时当日排名和当月排名搞反了!
作者: Seter 时间: 2009-11-21 21:43
回楼上的
修改好了...我发现问题在于用于辨别的变量p被我设定为环境变量了,所以我调试的时候if defined p是通过的,结果我就把对的改错了..
作者: Seter 时间: 2009-11-22 10:15
什么?连标题中的"部门 当天排名 当月累计排名"都是不确定的!?
作者: more 时间: 2009-11-24 16:28
还是让合适的工具来做最适合的工作吧,以前我先用bat来处理数据,发现效率太低了,后来又用bat调用vbs处理,感觉没那么顺手,接触到vba后,哈哈,有了相见恨晚的感觉...
我想,可能batman还不知道excel里有一个叫做vba(快捷键为Alt+F8)的东西吧,用VBE(快捷键Alt+F11)编写的,用下面的代码(vba)就高效多了,哈哈...- Option Explicit
-
- Sub JustDoIt()
- Dim AllColumns As Integer, AllRows As Integer, i As Integer, j As Integer, ADuty As Integer, Info As String, _
- Info2 As String
- AllColumns = Range("iv1").End(xlToLeft).Column '获取数据区列数
- AllRows = Range("a65536").End(xlUp).Row '获取数据区行数
- For i = 2 To AllColumns - 2
- Info = ""
- ADuty = 0
- For j = 2 To AllRows
- If Cells(j, i) > 0 Then
- ADuty = ADuty + Cells(j, i)
- Else
- Info = Info & Cells(j, 1) & ","
- End If
- Next
- If Info = "" Then Info = "无"
- Cells(i, AllColumns + 1) = Cells(1, i) & ADuty & ", 完成为 0 的局: " & Info
- Next
- Info = "当日排名: "
- Info2 = "当月累计排名: "
- For i = 1 To AllRows
- For j = 2 To AllRows
- If Cells(j, AllColumns - 1) = i Then Info = Info & Cells(j, 1) & i & ","
- If Cells(j, AllColumns) = i Then Info2 = Info2 & Cells(j, 1) & i & ","
- Next
- Next
- Cells(AllColumns, AllColumns + 1) = Info & vbCrLf & Info2
- Columns(AllColumns + 1).AutoFit
- Cells(AllColumns, AllColumns + 1).Select
- End Sub
复制代码
作者: batman 时间: 2009-11-24 16:40 标题: 回复 38楼 的帖子
vba我怎么会不知道啊,呵呵,最简单的不是你这样的,而是用excel的函数来解决。
作者: more 时间: 2009-11-24 16:52
函数完成不了1楼要求的显示效果吧,而在33楼你却说实际工作中是用vbs来操作的嘛...还生成一个b.txt...
作者: zqz0012005 时间: 2009-11-24 19:07 标题: 回复 40楼 的帖子
vbs可以调用excel,同时还可以让这个excel执行VBA,并调用其中的函数。
所以说vbs是强大滴。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |