Board logo

标题: [挑战] 批处理寻找所有条件里相同的数字 [打印本页]

作者: flyinspace    时间: 2008-10-17 13:20     标题: [挑战] 批处理寻找所有条件里相同的数字

假设有如下数字:

2190717
219117
2199817
2190517
2191417
21921917

为了大量数据统计的需要,我用一句话生成类似的数据
for /l %%i in (1,1,100) do echo 219%%i17>>1.txt

在这堆数据里,都有 219 的前缀和 17 的后缀,而中间的数据是随机的。

现在,我们的题目来了:
       利用批处理,找出 219 的前缀 和  17 的后缀,并将去掉后的结果输出到2.txt

输出的结果类似:
1
2
3
……
100

      前提:219 和 17在题目中是未知的,所以我们需要找出这2个未知的数据。。(这也是这里的难点)
作者: pusofalse    时间: 2008-10-17 13:47

有意思的题目,好好想想。。。
作者: batman    时间: 2008-10-17 16:56

写了个删除前缀的(后缀亦然),效率不怎么高:
  1. @echo off&setlocal enabledelayedexpansion
  2. set /p str=<1.txt
  3. :lp
  4. for /f "delims=" %%i in ('findstr "%var%%str:~,1%" 1.txt') do set /a n+=1
  5. if not defined num set "num=%n%"
  6. if "%n%" equ "%num%" (
  7.    set "var=%var%%str:~,1%"&set "str=%str:~1%"
  8.    set "n=0"&goto lp
  9. )
  10. for /f "delims=" %%i in (1.txt) do (
  11.     set "str=%%i"
  12.     echo !str:%var%=!
  13. )
  14. pause>nul
复制代码

作者: pusofalse    时间: 2008-10-17 17:09

  1. @echo off&setlocal enabledelayedexpansion
  2. set /p str=<a.txt
  3. set /a n=-1
  4. :loop
  5. set/a n+=1
  6. for /f "delims=" %%a in (a.txt) do (
  7.      set "var=%%a"
  8.      if "!var:~%n%,1!" neq "!str:~%n%,1!" set "x=%n%"
  9.      set "str=%%a"
  10. )
  11. if not defined x goto loop
  12. for /f "delims=" %%i in (a.txt) do (
  13.      set "var=%%i"
  14.      echo !var:~%x%!
  15. )
  16. pause
复制代码
也来一个,同样只是去掉前缀。输出结果跟batman版主的代码有点出入。
作者: batman    时间: 2008-10-17 17:23

思维定向了,一直想先把前缀提出来,pusofalse版主的代码证明了并不要提出来。
作者: pusofalse    时间: 2008-10-17 17:34

再修改下,能正确输出1,2,3、、、、100。
  1. @echo off&setlocal enabledelayedexpansion
  2. cd.>a.txt
  3. set/a r=%random%,d=!random!,n=-1
  4. for /l %%a in (1 1 100) do set "_!random!!random!=%r%%%a%d%"
  5. for /f "tokens=2 delims==" %%i in ('set _') do echo>>a.txt %%i
  6. set /p str=<a.txt
  7. :loop
  8. set/a n+=1,m+=1
  9. for /f "delims=" %%a in (a.txt) do (
  10.      set "var=%%a"
  11.      if "!var:~%n%,1!" neq "!str:~%n%,1!" if not defined x set "x=%n%"
  12.      if "!var:~-%m%,1!" neq "!str:~-%m%,1!" if not defined y set "y=%m%"
  13.      set "str=%%a"
  14. )
  15. for %%a in (x y) do if not defined %%a goto loop
  16. set/a y-=1
  17. for /f "delims=" %%i in (a.txt) do (
  18.      set "var=%%i"
  19.      echo !var:~%x%,-%y%!
  20. )
  21. pause>nul
复制代码

[ 本帖最后由 pusofalse 于 2008-10-17 18:28 编辑 ]
作者: youxi01    时间: 2008-10-17 19:16

我在思考一个问题,或者询问楼主:
在这里,究竟是人工识别前缀还是要求自动识别?
作者: flyinspace    时间: 2008-10-17 19:21

原帖由 youxi01 于 2008-10-17 19:16 发表
我在思考一个问题,或者询问楼主:
在这里,究竟是人工识别前缀还是要求自动识别?

当然是自动识别前缀和后缀来呀。。

若是人工识别,这个题目就没有难度了。。

这个是对字符串知识的一次总结。。
作者: 随风    时间: 2008-10-17 20:43

:
  1. @echo off&setlocal enabledelayedexpansion
  2. set /p var=<a.txt
  3. set q=%var:~0,1%
  4. set h=%var:~-1%
  5. for /f "delims=:" %%a in ('findstr /n "." a.txt') do set /a z=%%a
  6. :loop
  7. for /f "delims=:" %%a in ('findstr /n "^%q%" a.txt') do set /a x=%%a
  8. if %x% equ %z% (
  9.    set /a m+=1
  10.    set "q=!q!!var:~1,1!"
  11.    set "var=!var:~1!"
  12.    goto loop
  13. )
  14. :loop2
  15. for /f "delims=:" %%a in ('findstr /n "%h%$" a.txt') do set /a x=%%a
  16. if %x% equ %z% (
  17.    set /a j+=1&set var=!var:~0,-1!
  18.    set h=!var:~-1,1!!h!
  19.    goto loop2
  20. )
  21. for /f "delims=" %%a in (a.txt) do (
  22.    set "str=%%a"
  23.    echo !str:~%m%,-%j%!
  24. )
  25. pause
复制代码

作者: namejm    时间: 2008-10-17 23:08

  既然前缀和后缀是未知的,又怎么找得出来呢?楼主提供的条件让人不解,难道是说,如果前缀和后缀重复的次数达到一定次数之后,就要把这些数据过滤掉?
作者: zqz0012005    时间: 2008-10-17 23:45

和JM有相同的疑问,假如有下面的数据:
2190717
2190117
2190117
2193117
2191117
这要比较很多组才能判断出正确的前缀和后缀吧?效率很难保证
作者: youxi01    时间: 2008-10-18 00:48

同楼上
个人感觉,在这方面,机器的效率还是比不上人脑的
作者: batman    时间: 2008-10-18 11:31

我觉得楼主的意思还是表明清楚了,这个每行的前缀和后缀也是能通过程度自动判断出来
的,但用纯批处理来完成这样一个过程必定存在效率问题,因为用批肯定是要进行逐字符
判断的,当遇到大型的文本时,这样的处理将会慢得不可形容。所以,这样的题目其实际
价值并不会太大。。。
作者: namejm    时间: 2008-10-18 12:43

  楼主的意思并没有表明清楚,因为楼主并没有说清楚什么样的字符串才算前缀,什么样的字符串才算后缀,既然前缀后缀的含义都没有交代清楚,又怎么能让程序判断哪些是前缀哪些是后缀呢——楼主已经注明了,219和17仅仅是举例,它们是未知的,是需要通过程序来判断,这是问题的关键。
作者: wxcute    时间: 2008-10-18 15:16     标题: 据pusofalse四楼代码而改

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. call :loop n-1 fx
  4. call :loop -n lx
  5. set/a fx=fx,lx=lx+1
  6. for /f "delims=" %%i in (1.txt) do (
  7.      set "var=%%i"
  8.      echo !var:~%fx%,%lx%!
  9. )
  10. pause
  11. goto :eof
  12. :loop
  13. set/a n+=1
  14. set/a m=%1
  15. for /f "delims=" %%a in (1.txt) do (
  16.      set "var=%%a"
  17.      if not "!str!"=="" if not "!str:~%m%,1!"=="!var:~%m%,1!" set "%2=%m%"
  18.      set "str=%%a"
  19. )
  20. if not defined %2 goto loop
  21. set n=
复制代码

作者: batman    时间: 2008-10-18 17:52

原帖由 namejm 于 2008-10-18 12:43 发表
  楼主的意思并没有表明清楚,因为楼主并没有说清楚什么样的字符串才算前缀,什么样的字符串才算后缀,既然前缀后缀的含义都没有交代清楚,又怎么能让程序判断哪些是前缀哪些是后缀呢——楼主已经注明了,219和17仅 ...

我理解的就是,文本每行前面和后面都包含有的字符串就是前缀和后缀。
作者: rat    时间: 2008-10-18 21:59

  1. @echo off && setlocal enabledelayedexpansion
  2. call :i l +
  3. call :i r -
  4. set /a r+=1
  5. for /f %%a in (1.txt) do set "v=%%a" && echo !v:~%l%,%r%!>>2.txt
  6. goto :eof
  7. :i
  8. set "?=%2"
  9. set "s="
  10. if "%?%"=="+" (set i=0) else (set i=-1)
  11. :repeat
  12. for /f %%a in (1.txt) do set "v=%%a" && set "s=!s!!v:~%i%,1!"
  13. set "v=!v:~%i%,1!"
  14. set "s=!s:%v%=!"
  15. if not defined s (set /a i%?%=1 && goto repeat) else (set %1=%i%)
复制代码

作者: flyinspace    时间: 2008-10-19 12:17

我的思路是这样的。

假设有1000组数据。。

任意取两个数据进行比较,取相同的数据作为参考量。
假设 2910117
          2910217
这两个数据,就取到了 2910 这个参考。

然后进行一次 Findstr /r "^2910" 的输出查找,看找到的数据量是否有1000条。
若不满足1000条,则取  291 查找,看是否有1000条。直到满足

或者
一个一个的向后取值
例如 findstr /r "^2"  直到不满足条件为止。。

不过,我发现你们的代码可能更适合一些了 。。

继续研究一下,看是否有BUG呢。
作者: everest79    时间: 2008-10-20 03:50

得到前辍使用sort +n来识别

sort +1 & sort +2  & sort +3
作者: lovelymorning    时间: 2008-11-1 19:18

原帖由 flyinspace 于 2008-10-19 12:17 发表
我的思路是这样的。

假设有1000组数据。。

任意取两个数据进行比较,取相同的数据作为参考量。
假设 2910117
          2910217
这两个数据,就取到了 2910 这个参考。

然后进行一次 Findstr /r "^2910" ...



按照您这个思路,干脆叫cmd去跳楼吧。。。


这么比较,都不知要花费多少时间在这里面。。。何况比到最后,都不一定能比出个结果。。。就算有结果了。。。也不一定正确。。。
作者: lorn1234    时间: 2009-1-11 14:53

原帖由 batman 于 2008-10-17 16:56 发表
写了个删除前缀的(后缀亦然),效率不怎么高:@echo off&setlocal enabledelayedexpansion
set /p str=nul

有点问题,把生成的1.txt取反后得到的结果有BUG,对这行7171912 删前缀得到的结果是912

[ 本帖最后由 lorn1234 于 2009-1-12 00:55 编辑 ]
作者: netbenton    时间: 2009-4-21 00:36

用sort 排序一次后,只需比较第一条和最后一条记录即可得出前缀了。

=========================
set /p one=<a.txt
...测串长
for /f "delims=" %%a in (a.txt) do (set str=%%a
set f1=!str:~1,1!
set f2=!str:~2,1!
set f3=!str:~3,1!

...根据串长动态生成行数,变%var1%代替代码行
set r1=!str:~-1!
set r2=!str:~-2!
set r3=!str:~-3!

...
)

最后再与第一条记录的比较就可以得到前后缀了。
作者: netbenton    时间: 2009-4-22 13:43     标题: 做出来了

  1. @echo off
  2. set $=!
  3. setlocal enabledelayedexpansion
  4. (for /l %%i in (1,1,100) do echo 219%%i17)>%~n0.txt
  5. set /p var=<%~n0.txt
  6. set com=
  7. set bom=
  8. for /l %%a in (0,1,32) do (
  9.         set "bom=!bom!&set #b%%a!$!str:~-%%a,1!$!=!$!str:~-%%a,1!$!"
  10.         if "!var:~%%a,1!"=="" goto :scok
  11.         set "com=!com!&set #c%%a!$!str:~%%a,1!$!=!$!str:~%%a,1!$!"
  12. )
  13. :scok
  14. set com=!com:~1!
  15. set bom=!bom:~1!
  16. set "bom=!bom:*&=!"
  17. for /f %%i in (%~n0.txt) do (set str=%%i
  18. %com%
  19. %bom%
  20. )
  21. set var=
  22. set tou=
  23. for /f "tokens=1,2 delims==" %%a in ('set #c') do (set str=%%a
  24.         if "!str:~2,1!"=="!var!" goto :oktou
  25.         set tou=!tou!%%b
  26.         set var=!str:~2,1!
  27. )
  28. :oktou
  29. set wei=
  30. set var=
  31. for /f "tokens=1,2 delims==" %%a in ('set #b') do (set str=%%a
  32.         if "!str:~2,1!"=="!var!" goto :okwei
  33.         set wei=%%b!wei!
  34.         set var=!str:~2,1!
  35. )
  36. :okwei
  37. echo %tou:~,-1%     %wei:~1%
  38. pause
复制代码

[ 本帖最后由 netbenton 于 2009-4-22 18:25 编辑 ]
作者: 随风    时间: 2009-4-22 14:17     标题: 回复 24楼 的帖子

Q:所发代码不止一行时请用 code 把代码扩起来
A:如何用code把代码扩起来 ,请点我。
未细看你的代码,但若你是按22楼所说的思路来解的话,可能有考虑不周的地方。
楼主题意描述不清,我们假设所谓的 前缀和后缀 是指所有行都有的特征。
如果你sort排序后得到的第一行和最后一行分别是以下两行,能得到正确结果吗?
假设前缀为 1234
后缀为 4321
sort排序后
第一行为 1234555674321
最后一行为 12345556743214321
作者: netbenton    时间: 2009-4-22 18:42

回版主:
不好意思,偶知道怎么加code,只是回贴时,粘贴后就马上点发表了,没注意,谢谢提醒。
以后一定注意。



偶在22楼是没有表达得清楚,并且有很大错误,不好意思。

其实是想说:
方法一,sort后可以对比前后行仅仅得出前缀。后缀没有解决。(发现确实不行)
方法二,(24楼代码)则可以分别得出前、后缀,并且速度还可以。(可行,但与22楼表达的有点不同)


完整代码如下(文本文件名与批处理文件名关联了,1000行记录3秒内完成替换):

  1. @echo off
  2. set $=!
  3. setlocal enabledelayedexpansion
  4. (for /l %%i in (1,1,1000) do echo 219%%i17)>%~n0.txt
  5. set /p var=<%~n0.txt
  6. set com=
  7. set bom=
  8. for /l %%a in (0,1,32) do (
  9. set "bom=!bom!&set #b%%a!$!str:~-%%a,1!$!=!$!str:~-%%a,1!$!"
  10. if "!var:~%%a,1!"=="" goto :scok
  11. set "com=!com!&set #c%%a!$!str:~%%a,1!$!=!$!str:~%%a,1!$!"
  12. )
  13. :scok
  14. set com=!com:~1!
  15. set bom=!bom:~1!
  16. set "bom=!bom:*&=!"
  17. for /f %%i in (%~n0.txt) do (set str=%%i
  18. %com%
  19. %bom%
  20. )
  21. set var=
  22. set tou=
  23. for /f "tokens=1,2 delims==" %%a in ('set #c') do (set str=%%a
  24. if "!str:~2,1!"=="!var!" goto :oktou
  25. set tou=!tou!%%b
  26. set var=!str:~2,1!
  27. )
  28. :oktou
  29. set wei=
  30. set var=
  31. for /f "tokens=1,2 delims==" %%a in ('set #b') do (set str=%%a
  32. if "!str:~2,1!"=="!var!" goto :okwei
  33. set wei=%%b!wei!
  34. set var=!str:~2,1!
  35. )
  36. :okwei
  37. set tou=%tou:~,-1%&set wei=%wei:~1%
  38. ::前面的找前后缀,后面的进行替换
  39. (for /f %%i in (%~n0.txt) do (set str=#%%i#
  40. set str=!str:#%tou%=!
  41. echo !str:%wei%#=!
  42. ))>%~n0dest.txt
  43. start %~n0dest.txt
  44. pause
复制代码

[ 本帖最后由 netbenton 于 2009-4-22 19:03 编辑 ]
作者: 随风    时间: 2009-4-22 19:22     标题: 回复 26楼 的帖子

能把思路说说吗?看代码太累了!
作者: netbenton    时间: 2009-4-22 22:37

根据第一行的长度,取得动态代码行:

内容为:set  #c0!str:~0,1!=!str:~0,1!&set  #c1!str:~1,1!=!str:~1,1!  ...

%com%=从串首开始
%bom%=从串尾开始

变量定义规则:  #c+列号+字符=字符

这样会根据各列字符,动态定义变量,如果同一列有不同字符,则会定义多个变量,否则只有一个

for +set 最后判断同一列是否有二个以上变量,即可知道是否为前/后缀结束

[ 本帖最后由 netbenton 于 2009-4-22 22:43 编辑 ]
作者: 基拉freedom    时间: 2009-7-13 14:58


这个有点像在许多字符串中找到相同的字符串~
作者: Seter    时间: 2009-8-16 09:00

为什么我还是没看懂题目...
既然是自动截开头,,那么219开头也可以被认为21开头啊..
作者: caruko    时间: 2009-12-7 17:48

sort 之后,第一行与最后一行,对比分析,应该可以得到前缀吧

后缀的话,开始是想,二进制后几位也相同,用>> 移位,然后 mod 2 , 如果移位后,最后一位都是0或者1,那么MOD值也相同,如果有0有1,那么MOD值就不同,然后根据移位的位数,来分析后缀。
测试了下,咳..数字运算只能支持2^32,数字过长就没办法了..

只能当作字符串测试了,检查 %str:~-n+1,-n% 是不是相同了..效率估计不高

[ 本帖最后由 caruko 于 2009-12-8 11:41 编辑 ]




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2