标题: [文本处理] 【已解决】批处理:统计累计出现次数 [打印本页]
作者: 思想之翼 时间: 2013-2-16 20:23 标题: 【已解决】批处理:统计累计出现次数
本帖最后由 思想之翼 于 2013-2-28 10:48 编辑
批处理:统计累计出现次数
一个文件夹中有63个txt文本,名为01.txt、02.txt、03.txt......63.txt。这63个文本的数值排列格式一致。
比如,序号为01的txt文本中有如下数值:
0000001 4 9 2 2
0000002 9 2 2 0
0000003 2 2 0 3
0000004 2 0 3 5
0000005 0 3 5 9
0000006 3 5 9 5
......
......
数值的前七位是序号,后四位由左到右分别记为1 2 3 4位。
现在拿第一行的0000001 4 9 2 2举例,欲做如下分步统计,得出最后想要的数值:
1、将四位数4 9 2 2的1 2 3 4位两两相加、减、乘,即1+2,1+3,1+4,2+3,2+4,3+4,1-2,1-3,1-4,2-3,2-4,3-4,1*2,1*3,1*4,2*3,2*4,3*4,得到数值3 6 6 1 1 4 5 2 2 7 7 0 6 8 8 8 8 4;
2、在得到的数值中,统计0 1 2 3 4 5 6 7 8 9分别出现几次。(此例中,数值0出现1次,数值1出现2次,数值2出现2次,数值3出现3次,数值4出现2次,数值5出现1次,数值6出现3次,数值7出现2次,数值8出现4次,数值9出现0次)
3、再统计0 1 2 3 4 5 6 7 8 9这10个数值中,五五相加累计出现的次数。(此例中,数值0+数值1+数值2+数值3+数值4,其累计出现次数是1次+2次+2次+3次+2次,即01234=1+2+2+3+2=10)
在0 1 2 3 4 5 6 7 8 9这10个数中,五五相加共有252种可能,即01234 01235 01236 01237 01238 01239 01245 01246 01247 01248 01249 01256 01257 01258 01259 01267 01268 01269 01278 01279 01289 01345 01346 01347 01348 01349 01356 01357 01358 01359 01367 01368 01369 01378 01379 01389 01456 01457 01458 01459 01467 01468 01469 01478 01479 01489 01567 01568 01569 01578 01579 01589 01678 01679 01689 01789 02345 02346 02347 02348 02349 02356 02357 02358 02359 02367 02368 02369 02378 02379 02389 02456 02457 02458 02459 02467 02468 02469 02478 02479 02489 02567 02568 02569 02578 02579 02589 02678 02679 02689 02789 03456 03457 03458 03459 03467 03468 03469 03478 03479 03489 03567 03568 03569 03578 03579 03589 03678 03679 03689 03789 04567 04568 04569 04578 04579 04589 04678 04679 04689 04789 05678 05679 05689 05789 06789 12345 12346 12347 12348 12349 12356 12357 12358 12359 12367 12368 12369 12378 12379 12389 12456 12457 12458 12459 12467 12468 12469 12478 12479 12489 12567 12568 12569 12578 12579 12589 12678 12679 12689 12789 13456 13457 13458 13459 13467 13468 13469 13478 13479 13489 13567 13568 13569 13578 13579 13589 13678 13679 13689 13789 14567 14568 14569 14578 14579 14589 14678 14679 14689 14789 15678 15679 15689 15789 16789 23456 23457 23458 23459 23467 23468 23469 23478 23479 23489 23567 23568 23569 23578 23579 23589 23678 23679 23689 23789 24567 24568 24569 24578 24579 24589 24678 24679 24689 24789 25678 25679 25689 25789 26789 34567 34568 34569 34578 34579 34589 34678 34679 34689 34789 35678 35679 35689 35789 36789 45678 45679 45689 45789 46789 56789
想要得到的,就是0-9这10个数值五五相加得到的252个数值。将这252个数值依次分为6组,每组42个,分别放置在6个新建的txt文本,文本数值排列格式都是0000001、0000002......等序号后依次排列42个数值。新建的6个txt文本,名为01_1,01_2,01_3,01_4,01_5,01_6,并放入新建的序号为01的文件夹。
以上是01.txt文本的批处理操作过程。另外序号为02、03......63的txt文本,同理操作,分别新建6个txt文本,并放置在新建的序号为02、03......63文件夹中。
上述操作,用excel函数可以解决,但步骤繁琐,故期盼使用批处理提高效率。恳望大师相助!
作者: group 时间: 2013-2-17 04:58
1、将四位数4 9 2 2的1 2 3 4位两两相加、减、乘,即1+2,1+3,1+4,2+3,2+4,3+4,1-2,1-3,1-4,2-3,2-4,3-4,1*2,1*3,1*4,2*3,2*4,3*4,得到数值3 6 6 1 1 4 5 2 2 7 7 0 6 8 8 8 8 4;- @echo off
- setlocal enabledelayedexpansion
- for /f "delims=" %%f in (dir /b ??.txt) do (
- for /f "tokens=1*" %%a in (%%f) do (
- set "a="
- for %%c in (%%b) do set /a a+=%%c
- echo !a!
- )
- )>%%~nf_1.txt
复制代码
2、在得到的数值中,统计0 1 2 3 4 5 6 7 8 9分别出现几次。(此例中,数值0出现1次,数值1出现2次,数值2出现2次,数值3出现3次,数值4出现2次,数值5出现1次,数值6出现3次,数值7出现2次,数值8出现4次,数值9出现0次)- @echo off
- setlocal enabledelayedexpansion
- for /f "delims=" %%f in (dir /b ??.txt) do (
- for /f "tokens=1*" %%a in (%%f) do (
- for %%c in (%%b) do set /a a[%%b]+=1
- )
- (for /l %%a in (0 1 9) do echo !a[%%a]!)>%%~nf_2.txt
- )
复制代码
3看不懂什么意思
作者: apang 时间: 2013-2-17 16:49
效率不高- @echo off
- for /f "delims=" %%i in ('dir /a-d /b *.txt') do (
- md "New\%%~ni\" 2>nul
- for /f "tokens=1*" %%j in (%%i) do (
- setlocal enabledelayedexpansion
- for %%a in (%%k) do set /a n+=1&set .!n!=%%a
- for %%a in (+ - x) do (
- set k=%%a
- for /l %%b in (1 1 4) do (
- set /a m=%%b+1
- for /l %%c in (!m! 1 4) do (
- set /a "s=.%%b !k:x=*! .%%c"&set /a "_!s:~-1!+=1"
- )
- )
- )
- set /a n=1,m=0
- for /l %%a in (0 1 9) do (
- set /a a=%%a+1&for /l %%b in (!a! 1 9) do (
- set /a b=%%b+1&for /l %%c in (!b! 1 9) do (
- set /a c=%%c+1&for /l %%d in (!c! 1 9) do (
- set /a d=%%d+1&for /l %%e in (!d! 1 9) do (
- set /a m+=1
- set /a s=_%%a+_%%b+_%%c+_%%d+_%%e
- set str=!str! !s!
- if !m! equ 42 (
- echo>>"New\%%~ni\%%~ni_!n!.txt" %%j!str!
- set "str="&set /a n+=1,m=0
- ))))))
- endlocal
- )
- )
- pause
复制代码
作者: 思想之翼 时间: 2013-2-17 19:24
回复 3# apang
谢谢!圆满解决问题!曾所谓“效率不高”,的确如此。此代码支持多核多线程吗?
作者: 思想之翼 时间: 2013-2-18 13:03
本帖最后由 思想之翼 于 2013-2-18 14:36 编辑
回复 3# apang
感谢大师倾情给出的代码!这些代码省却了我太多的繁琐操作。但是由于数据多,上述批处理代码完成一组数据的处理,需要花费近10个小时,只有晚上挂机了。好在每一次增加的数据不多,处理起来就快多了。这就带来一个问题:如何用批处理来合并前后2次处理的文件?前后2个文件夹里各有63个名为01-63的小文件夹,而每个小文件夹里又有6个名为01_1......01_6的txt文本,手工一一合并,繁琐自不言语,还可能出错。恳望大师再次帮助,写一个合并上述文本的批处理代码。在此先谢谢了!
作者: apang 时间: 2013-2-18 19:16
回复 5# 思想之翼
偶只是小菜菜鸟,不是大师,但很希望在某年某月能成为大师。。。
10个小时,没想到这么慢。。。下面是合并的代码,修改第2、3行路径为实际。- @echo off
- set "SrcDir1=C:\abc\New"
- set "SrcDir2=D:\123\New"
- set "DstDir=%~dp0合并"
- xcopy "%SrcDir1%\*.txt" "%DstDir%\" /sy >nul
- for /r "%DstDir%\" %%a in (*.txt) do (
- set "a=%%a"
- setlocal enabledelayedexpansion
- set "b=!a:%DstDir%=%SrcDir2%!"
- if exist "!b!" copy /b "!a!" + "!b!" "!a!"
- endlocal
- )
- pause
复制代码
作者: BAT-VBS 时间: 2013-2-18 23:00
回复 4# 思想之翼
BAT只能多进程不能多线程。
作者: group 时间: 2013-2-19 02:54
本帖最后由 group 于 2013-2-19 02:55 编辑
回复 3# apang
感觉反复生成 0~9 的五位数组合太耗时了,可不可以事先写入到文件中,再读文件呢?
还有 for %%a in (+ - x) do 这个循环好像也有点重复,我想可以这样来减少 2/3 的 set /a- set /a "s1=.%%b-.%%c,s2=.%%b+.%%c,s3=%%b*.%%c"
- set /a "_!s1:~-1!+=1,_!s2:~-1!+=1,_!s3:~-1!+=1"
复制代码
作者: apang 时间: 2013-2-19 14:58
回复 apang
感觉反复生成 0~9 的五位数组合太耗时了,可不可以事先写入到文件中,再读文件呢?
...
发表于 2013-2-19 02:54
group言之有理,感谢指点!
测试一个100行的文本,3楼要29秒跑完,下面的17秒跑完,相比修改之前快多了(虽然还是慢)。代码贴出来,不拍砖就好。。。- @echo off
- for /f "delims=" %%i in ('dir /a-d /b *.txt') do (
- md "New\%%~ni\" 2>nul
- (for /f "tokens=1*" %%j in (%%i) do (
- setlocal enabledelayedexpansion
- for %%a in (%%k) do set /a n+=1&set .!n!=%%a
- for /l %%b in (1 1 4) do (
- set /a m=%%b+1
- for /l %%c in (!m! 1 4) do (
- set /a "s1=.%%b+.%%c,s2=.%%b-.%%c,s3=.%%b*.%%c"
- set /a "_!s1:~-1!+=1,_!s2:~-1!+=1,_!s3:~-1!+=1"
- )
- )
- for /l %%a in (0 1 9) do (
- set /a a=%%a+1&for /l %%b in (!a! 1 9) do (
- set /a b=%%b+1&for /l %%c in (!b! 1 9) do (
- set /a c=%%c+1&for /l %%d in (!c! 1 9) do (
- set /a d=%%d+1&for /l %%e in (!d! 1 9) do (
- set /a s=_%%a+_%%b+_%%c+_%%d+_%%e
- set str=!str! !s!
- )))))
- echo,%%j!str!&endlocal
- ))>$
- for /f "tokens=1*" %%a in ($) do (
- set /a n=1&setlocal enabledelayedexpansion
- for %%c in (%%b) do (
- set /a m+=1&set str=!str! %%c
- if !m! equ 42 (
- >>"New\%%~ni\%%~ni_!n!.txt" echo,%%a!str!
- set "str="&set /a m=0,n+=1
- )
- )
- endlocal
- )
- )
- del $&pause
复制代码
作者: group 时间: 2013-2-19 15:48
回复 9# apang
借你代码小改一下- @echo off
- echo %time%
- setlocal enabledelayedexpansion
- (for /l %%a in (0 1 9) do (
- set /a a=%%a+1&for /l %%b in (!a! 1 9) do (
- set /a b=%%b+1&for /l %%c in (!b! 1 9) do (
- set /a c=%%c+1&for /l %%d in (!c! 1 9) do (
- set /a d=%%d+1&for /l %%e in (!d! 1 9) do (
- echo _%%a+_%%b+_%%c+_%%d+_%%e
- ))))))>$1
-
- (for /l %%b in (1 1 4) do (
- set /a m=%%b+1
- for /l %%c in (!m! 1 4) do (
- echo s1=.%%b+.%%c,s2=.%%b-.%%c,s3=.%%b*.%%c
- )
- ))>$2
- endlocal
-
- for /f "delims=" %%i in ('dir /a-d /b *.txt') do (
- md "New\%%~ni\" 2>nul
- for /f "tokens=1*" %%j in (%%i) do (
- setlocal enabledelayedexpansion
- set n=1
- for %%a in (%%k) do set /a .!n!=%%a,n+=1
-
- for /f %%a in ($2) do (
- set /a %%a
- set /a "_!s1:~-1!+=1,_!s2:~-1!+=1,_!s3:~-1!+=1"
- )
-
- set /a n=1,m=0
- for /f %%a in ($1) do (
- set /a m+=1,s=%%a
- set str=!str! !s!
- if !m! equ 42 (
- echo>>"New\%%~ni\%%~ni_!n!.txt" %%j!str!
- set "str="&set /a n+=1,m=0
- )
- )
- endlocal
- )
- )
- echo %time%
- del $?&pause
复制代码
作者: 思想之翼 时间: 2013-2-22 11:55
回复 10# group
谢谢!此VBA代码速度提高很多:100行数据自己实测,耗时12秒78;apang大师修订的,耗时17秒70
再次感谢apang、group两位大师的热心帮助!
作者: 思想之翼 时间: 2013-3-6 22:05
回复 10# group
非常感谢您写的代码,运算速度提高很快!但就是这样的速度,耗时也颇多。
在实际运用中,发觉还可以减少一半的数据运算量,特向大师请求,能否稍微改动一下代码?
怎样减少一半的数据运算量?大师请看:
在0 1 2 3 4 5 6 7 8 9这10个数中,五五相加共有252种可能,即
01234 01235 01236 01237 01238 01239 01245 01246 01247 01248 01249 01256 01257 01258 01259 01267 01268 01269 01278 01279 01289 01345 01346 01347 01348 01349 01356 01357 01358 01359 01367 01368 01369 01378 01379 01389 01456 01457 01458 01459 01467 01468 01469 01478 01479 01489 01567 01568 01569 01578 01579 01589 01678 01679 01689 01789 02345 02346 02347 02348 02349 02356 02357 02358 02359 02367 02368 02369 02378 02379 02389 02456 02457 02458 02459 02467 02468 02469 02478 02479 02489 02567 02568 02569 02578 02579 02589 02678 02679 02689 02789 03456 03457 03458 03459 03467 03468 03469 03478 03479 03489 03567 03568 03569 03578 03579 03589 03678 03679 03689 03789 04567 04568 04569 04578 04579 04589 04678 04679 04689 04789 05678 05679 05689 05789 06789 12345 12346 12347 12348 12349 12356 12357 12358 12359 12367 12368 12369 12378 12379 12389 12456 12457 12458 12459 12467 12468 12469 12478 12479 12489 12567 12568 12569 12578 12579 12589 12678 12679 12689 12789 13456 13457 13458 13459 13467 13468 13469 13478 13479 13489 13567 13568 13569 13578 13579 13589 13678 13679 13689 13789 14567 14568 14569 14578 14579 14589 14678 14679 14689 14789 15678 15679 15689 15789 16789 23456 23457 23458 23459 23467 23468 23469 23478 23479 23489 23567 23568 23569 23578 23579 23589 23678 23679 23689 23789 24567 24568 24569 24578 24579 24589 24678 24679 24689 24789 25678 25679 25689 25789 26789 34567 34568 34569 34578 34579 34589 34678 34679 34689 34789 35678 35679 35689 35789 36789 45678 45679 45689 45789 46789 56789
实际运用中,发觉01234--06789这一组数据,与12345--56789这一组数据,有着两两对应的关系,统计分析了01234--06789这一组数据的特性,也就没必要再对12345--56789这组数据做分析了。
也就是说,用大师所写的批处理代码,只要得到01234--06789这组数据就可以了,不必再继续运算出12345--56789这一组数据了。
作者: terse 时间: 2013-3-6 23:52
本帖最后由 terse 于 2013-3-7 00:04 编辑
..
非常感谢您写的代码,运算速度提高很快!但就是这样的速度,耗时也颇多。
在实际运用中 ...
思想之翼 发表于 2013-3-6 22:05
- for /L %%i in (0 1 9) do set /a @%%i=%%i+1
- (for /l %%A in (1 1 6) do (
- for /l %%B in (!@%%A! 1 7) do (
- for /l %%C in (!@%%B! 1 8) do (
- for /l %%D in (!@%%C! 1 9) do (
- echo+0+%%A+%%B+%%C+%%D
- )
- )
- )
- ))>$1
复制代码
作者: 思想之翼 时间: 2013-3-7 00:17
回复 13# terse
谢谢热心关注!仔细看了您的帖子,还是不完全知道怎样在楼上的帖子中修改,烦请修改一下贴在楼下,好吗?
作者: apang 时间: 2013-3-7 22:02
vbs的话,实测一个250行的文本,不用临时文件,1秒完成
作者: 思想之翼 时间: 2013-3-7 23:46
回复 15# apang
1秒完成,太高兴了。用哪一个代码?还有,运算时可以舍去252个组合里的12345--56789这一组,只运算01234到06789这126个组合就可以了,运算量又可以舍去一半。恳望得到老师的帮助!
作者: apang 时间: 2013-3-8 14:06
回复 16# 思想之翼 - T = Timer
- Set FSO = CreateObject("Scripting.FileSystemObject")
- If Not FSO.FolderExists("New") Then FSO.CreateFolder("New")
- For Each File in FSO.GetFolder(".").Files
- Ext = FSO.GetExtensionName(File)
- Name = FSO.GetBaseName(File)
- If LCase(Ext) = "txt" Then
- fDir = "New\" & Name
- If Not FSO.FolderExists(fDir) Then FSO.CreateFolder(fDir)
- Open_File FSO.OpenTextFile(File)
- End If
- Next
-
- MsgBox Timer - T
-
- Sub Open_File(f)
- Do Until f.AtEndOfStream
- Text = f.ReadLine
- If RegEx(Text) <> "" Then GetStr Split(RegEx(Text)," ")
- Loop
- End Sub
-
- Sub GetStr(ar)
- Dim A(9)
- For i = 0 to 9 :A(i) = 0 :Next
- For i = 1 to UBound(ar) - 1
- For j = i + 1 to UBound(ar)
- s1 = Right(CInt(ar(i)) + CInt(ar(j)),1) :A(s1) = A(s1) + 1
- s2 = Right(CInt(ar(i)) - CInt(ar(j)),1) :A(s2) = A(s2) + 1
- s3 = Right(CInt(ar(i)) * CInt(ar(j)),1) :A(s3) = A(s3) + 1
- Next
- Next
-
- For i = 1 to 6
- For j = i + 1 to 7
- For k = j + 1 to 8
- For L = k + 1 to 9
- ReDim PreServe B(n)
- B(n) = A(i) + A(j) + A(k) + A(L) + A(0)
- n = n + 1
- Next
- Next
- Next
- Next
-
- n = 1
- For i = 1 to UBound(B) + 1
- Str = Str & " " & B(i-1)
- If i Mod 42 = 0 Then
- FSO.OpenTextFile(fDir&"\"&Name&"_"&n&".txt",8,True).WriteLine ar(0)&Str
- Str = "" : n = n + 1
- End If
- Next
- End Sub
-
- Function RegEx(Text)
- Set Re = New RegExp
- Re.Pattern = "\s+"
- Re.Global = True
- RegEx = Trim(Re.Replace(Text," "))
- End Function
复制代码
作者: 思想之翼 时间: 2013-3-10 16:56
本帖最后由 思想之翼 于 2013-4-8 03:44 编辑
回复 17# apang
谢谢老师!该批处理代码运行速度很快!
该代码处理数据时,会新建一个New文件夹,其内又新建63个子文件夹,确实有利于数据分类管理。
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |