对整数进行排序并计算批处理文件中前20个的平均值

时间:2011-08-18 18:53:57

标签: batch-file dos

假设我有一个从文件中读取任意整数的批处理文件。该文件的结构使得每行包含一个整数,如下所示:

24
17
43
103
...

我需要计算文件中前20个数字的平均值。为了做到这一点,我需要某种存储前20个数字的数据结构。但是,据我所知,批处理文件中没有数组。我可能不得不求助于使用临时文件或其他一些我不知道的方法。所以我的最终目标是确定为批处理文件实现某种排序算法的最佳方法,并计算前20个整数的平均值。

我需要对问题进行约束。这个文件在大小方面非常大(约500行)所以我宁愿不使用临时文件,因为完成了大量的读/写操作(除非你当然可以说服我)。

4 个答案:

答案 0 :(得分:3)

您可以批量模仿数组。看看Using Arrays in Batch Files

答案 1 :(得分:2)

以下解决方案使用@ Stoney的答案中提供的链接文章中描述的数组。它还使用零填充进行正确排序,这是@jeb的一个好主意,尽管此解决方案不使用sort命令。相反,排序由SET命令自动完成,其输出用于迭代“数组”。

@ECHO OFF
SET top=5

SET cnt=0
FOR /F %%N IN (datafile) DO CALL :insert %%N
IF %cnt%==0 GOTO :EOF

IF %cnt% LSS %top% (SET threshold=0) ELSE SET /A threshold=cnt-top

SET s=0
SET i=0

FOR /F "tokens=2 delims=.=" %%A IN ('SET __number.') DO CALL :calc %%A

SET /A res=s/(cnt-threshold)-1000000
ECHO Average is %res%
PAUSE
GOTO :EOF

:insert
SET /A n=1000000+%1
SET /A __number.%n%+=1
SET /A cnt+=1
GOTO :EOF

:calc
SET /A i_prev=i
SET /A i+=__number.%1
IF %i% LEQ %threshold% GOTO :EOF
IF %i_prev% GEQ %threshold% (
  SET /A s+=%1*__number.%1
) ELSE (
  SET /A "s+=%1*(i_prev+__number.%1-threshold)"
)

基本上,该解决方案实现了以下算法:

  1. 逐个从文件中选择数字:

    1.1。如果是第一次遇到该号码,请将其添加到计数为1的数组中。

    1.2。如果该数字与已添加的数字重复,则将相应的计数值增加1。

    1.3。将总数增加1。

  2. 计算阈值,即总计数减去要计算平均值的最大数量。

  3. 迭代这样的数组项:

    3.1。将索引增加当前数字的计数值。

    3.2。如果索引超过阈值:

    • 如果它在当前迭代时已超过阈值,请将总和增加数量与其计数部分超出阈值的乘积。

    • 如果先前超过了阈值,请按总数和计数的乘积增加总和。

    3.3。如果索引未超过阈值,请省略该项目。

  4. 计算平均值作为总和除以总计数与门槛之差。

答案 2 :(得分:1)

您可以使用sort命令对数字进行排序,但是有问题,该排序使用字符串排序而不对数字进行排序,因此2似乎大于10。 但是如果将所有数字格式化为相同的长度到临时文件中,这可以解决 所以你得到了

024
017
043
103
...

使用/ R(反向)选项对它们进行排序,以最大数字开始输出。

然后你可以简单地读取20行并构建平均值

答案 3 :(得分:0)

用于小文件:

@Echo oFF

for /f %%a in (f1.txt) do Call :Append %%a
call :sort %sort%
pause
goto :EOF

:Append
call set sort=%%sort%% %*
goto :eof

:Sort
Setlocal EnableDelayedExpansion
Set/A n=1,s=0,c=s,r=s
for %%: In (%*) do (
    Set /a c+=1
    Set "nm.!c!=%%:")
:LP.1
if %s% EQU %c% Set/A n+=1,s=0
    Set/A s+=1
    Call :SPL %n% %s%
If %n% LEQ %c% goto :LP.1
:LP.2
    Echo:!nm.%c%!
    Set/A c-=1
If %c% GTR 0 goto :LP.2 
Endlocal & goto :EOF
:SPL
 If !nm.%1! GTR !nm.%2! (
   Set "t=!nm.%2!"&Set "nm.%2=!nm.%1!"
   Set "nm.%1=!t!"
 ) 
goto :EOF

或变体:

 @echo off
 for /f %%# in (f1.txt) do (
    set x=##########%%#
    call set #%%x:~-0xa%%==)
 for /f "delims=#=" %%a in ('set ##') do echo(%%a
 pause 

还有:gnu sort