如何在嵌套时更快地进行循环处理

时间:2018-04-07 14:44:10

标签: batch-file

1.嵌套时如何使循环处理更快。从(a)到(zzzzz)处理1个字符需要30秒

2.如何使此代码能够设置范围,例如开始2位数并以4位数结束。

3.为什么这段代码显示编码命令,这就是为什么我从命令

中输入character @ at

Sample.bat

@echo off     
setlocal EnableDelayedExpansion     

set "loop2=IN (0,1,36) DO @("     

set "n0="           
set "n1=a"     
set "n2=b"     
set "n3=c"     
set "n4=d"     
set "n5=e"     
set "n6=f"     
set "n7=g"     
set "n8=h"     
set "n9=i"     
set "n10=j"     
set "n11=k"     
set "n12=l"     
set "n13=m"     
set "n14=n"     
set "n15=o"     
set "n16=p"     
set "n17=q"     
set "n18=r"     
set "n19=s"     
set "n20=t"
set "n21=u"     
set "n22=v"     
set "n23=w"     
set "n24=x"     
set "n25=y"     
set "n26=z"     

set "n27=1"     
set "n28=2"     
set "n29=3"     
set "n30=4"     
set "n31=5"
set "n32=6"     
set "n33=7"     
set "n34=8"     
set "n35=9"     
set "n36=0"     

@FOR /L %%a %loop2%     
    @call :prc %%a      
    @FOR /L %%b %loop2%     
        @call :prc %%a %%b     
        @FOR /L %%c %loop2%     
            @call :prc %%a %%b %%c     
            @FOR /L %%d %loop2%     
                @call :prc %%a  %%b %%c %%d     
                @FOR /L %%e %loop2%     
                    @call :prc %%a %%b %%c %%d %%e     
                )     
            )     
        )     
    )     
)     
)     
@pause     
:prc     
::@cls     
@title %1 %2 %3 = !n%1!!n%2!!n%3!      
@set "data=!n%1!!n%2!!n%3!!n%4!!n%5!"      
@if not defined data goto end     
@echo.     
@echo %data% >> data.txt     
@echo.     
@:end     
@goto :eof     
`

3 个答案:

答案 0 :(得分:5)

我弄清楚为什么ECHO OFF有时似乎不起作用 - 当你打印两位数的字符串时,你最终会到达" on",这会产生echo on。很明显为什么这是一个问题!

你应该使用安全形式的ECHO,其中最好的是echo( - 它看起来很奇怪,但它确实有效。

考虑到优化的性能,Aacini的解决方案是第一个出现在我脑海中的想法。但是如果你真的想要最好的性能,你应该完全消除循环中的环境变量扩展。这可以通过切换到直接迭代符号(数字)的简单FOR来轻松完成。

您声明要控制每个字符串打印的最小和最大位数。这可以通过添加一些IF语句轻松完成。但IF需要时间来执行。最好将整个嵌套循环集合动态地构建为单个代码串。这样,您的主循环总是被优化,以尽可能少地完成工作。

这是我的优化版本。我在你的原始代码中随意将最大位数限制为5。虽然最终代码必须符合~8192个字符,但可以很容易地扩展。理论上支持最多68位的字符串,但如果该程序完成时人类仍然存在于这个星球上将是非常了不起的!地狱,到那时地球可能已经很久了!

:: %1 = min number of digits, between 1 and 5. Default = 1
:: %2 = max number of digits, between 1 and 5. Default = 5
::
@echo off
setlocal enableDelayedExpansion

:: Configuration
set /a "min=1, max=5"
if "%~1" neq "" set "min=%~1"
if "%~2" neq "" set "max=%~2"
if %min% lss 1 set min=1
if %max% lss 1 set min=1
if %min% gtr 5 set min=5
if %max% gtr 5 set max=5

:: Define symbols to be iterated by simple FOR
:: Use of simple FOR improves performance by eliminating environment variable
:: dereferencing within main loops.
set "chars=a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 0"

:: Dynamically build code as a "macro"
:: This enables configuration of number of digits printed, yet improves performance
:: by avoiding IF within main loops.
set "code="
set "digits="
for /l %%N in (1 1 %max%) do (
  set "code=!code!for %%%%N in (%chars%) do "
  set "digits=!digits!%%%%N"
  if %%N geq %min% (
    set "code=!code!echo(!digits!"
    if %%N lss %max% set "code=!code!&"
  )
)

:: Show the resultant code
echo !code!

:: Execute the code
>data.txt (%code%)

使用最小值1和最大值4,在我的机器上完成需要35秒。将max增加到5将至少需要21分钟。相比之下,从Aacini代码中消除内循环,修复ECHO ON问题,在我的机器上生成长度为1到4的所有字符串需要85秒。

下面是由min = 2,max = 3生成的代码,只需1秒即可完成。我故意使用引用块而不是代码块来避免过度的水平滚动。

  

for%1 in(abcdefghijklmnopqrstu vwxyz 1 2 3 4 5 6 7 8 9 0)for%2 in(abcdefghijklmnopqrstu vwxyz 1 2 3 4 5 6 7 8 9 0)do echo(%1%2& for% 3 in(abcdefghijklmnopqrstu vwxyz 1 2 3 4 5 6 7 8 9 0)做回声(%1%2%3

请注意,以上是展开%code%后的代码,因此%1表示FOR变量,而不是第一个批处理脚本参数。

答案 1 :(得分:3)

LotPings' answer中给出的建议外,还有两种构造特别慢:

  • call命令。如果你想要速度,请避免调用子程序。您可以使用(与原始的loop2变量一样,但使用完整的命令)。
  • >>重定向。此表单在每次使用时都执行以下步骤:1 - 打开文件。 2寻找文件的结尾。 3 - 附加数据。 4 - 关闭文件。 更快使用唯一的>重定向,使文件始终保持打开状态,直到流程结束。

我还修改了你的代码,以使其更具可读性:

@echo off
setlocal EnableDelayedExpansion

set "i=0"
for %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 0) do (
   set /A i+=1
   set "n!i!=%%a"
)

set "range2=1,1,36"

(FOR /L %%a IN (%range2%) DO (
    echo !n%%a!
    FOR /L %%b IN (%range2%) DO (
        echo !n%%a!!n%%b!
        FOR /L %%c IN (%range2%) DO (
            echo !n%%a!!n%%b!!n%%c!
            FOR /L %%d IN (%range2%) DO (
                echo !n%%a!!n%%b!!n%%c!!n%%d!
                FOR /L %%e IN (%range2%) DO (
                    echo !n%%a!!n%%b!!n%%c!!n%%d!!n%%e!
                )
            )
        )
    )
)) > data.txt

答案 2 :(得分:2)

  1. 如何在嵌套时更快地进行循环处理? 删除所有不必要的命令。

  2. 如何使此代码能够设置范围?
    采用不同的递归方法构建字符串,
    看起来像是在做差异。数字基数。
    BTW 36 power 5是60.466.176,通常你以
    开头 数字0后跟九个像十六进制0-9abcdef

  3. 后的字母
  4. 为什么此代码显示编码命令?
    Echo off

  5. 不会发生在这里

    禁用文件输出,只需写入控制台和 从第一个字母开始。

    @echo off & setlocal EnableDelayedExpansion
    set "n= abcdefghijklmnopqrstuvwxyz1234567890"
    for /l %%n in (1,1,36) do set "n%%n=!n:~%%n,1!"
    set "n="
    
    set "loop2=in (1,1,36) DO ("
    
    FOR /L %%a %loop2%
        call :prc %%a
        FOR /L %%b %loop2%
            call :prc %%a %%b
            FOR /L %%c %loop2%
                call :prc %%a %%b %%c
                FOR /L %%d %loop2%
                    call :prc %%a %%b %%c %%d
                    FOR /L %%e %loop2%
                        call :prc %%a %%b %%c %%d %%e
                    )
                Pause
                )
            )
        )
    )
    pause
    Goto :Eof
    :prc
    set "data=!n%1!!n%2!!n%3!!n%4!!n%5!"
    echo %data% &Rem>> data.txt
    goto :eof