Board logo

标题: [文本处理] 批处理如何将目录行索引切分为目录列索引 [打印本页]

作者: pan528    时间: 2013-6-1 11:06     标题: 批处理如何将目录行索引切分为目录列索引

本帖最后由 pan528 于 2013-6-1 11:12 编辑

材料条件和要求:
1、目录行索引是不断增加的,因此是不确定;
2、考虑通用性,目录列也是可调整的,有一定范围的,如3-15列中的一个。

可能的问题:
1、一定的目录行索引切分为指定的目录列索引,可能不被整除。即需要补空格才能使各列对齐;
2、从阅读习惯上看,对最后一列补齐比较符合一般情况。但:
34行切成11列、28行切成9列、12行切成5列等等情形,光补最后一列就会成为空列。这时就要采用补齐其他列的方法来对齐 ...

材料举例:
目录行索引
  1. 最高人民法院公报
  2. 1985年
  3.  第01期
  4.  第02期
  5.  第03期
  6.  第04期
  7. 1986年
  8.  第01期
  9.  第02期
  10.  第03期
  11.  第04期
  12. 1987年
  13.  第01期
  14.  第02期
  15.  第03期
  16.  第04期
  17. 1988年
  18.  第01期
  19.  第02期
  20.  第03期
  21.  第04期
  22. 1989年
  23.  第01期
  24.  第02期
  25.  第03期
  26.  第04期
复制代码
目录列索引(切分为五列)

最高人民法院公报                1986年                         第01期                         第02期                         第03期       
1985年                         第01期                         第02期                         第03期                         第04期       
 第01期                         第02期                         第03期                         第04期       
 第02期                         第03期                         第04期                        1989年
 第03期                         第04期                        1988年                         第01期       
 第04期                        1987年                         第01期                         第02期       



目录列索引(切分为三列)
  1. 最高人民法院公报  第03期  第02期
  2. 1985年  第04期  第03期
  3.  第01期 1987年  第04期
  4.  第02期  第01期 1989年
  5.  第03期  第02期  第01期
  6.  第04期  第03期  第02期
  7. 1986年  第04期  第03期
  8.  第01期 1988年  第04期
  9.  第02期  第01期
复制代码
目录列索引(切分为五列12/5的特殊情形)
最高人民法院公报                 第02期                        1986年                         第02期                         第04期       
1985年                         第03期                         第01期                         第03期                        1987年
 第01期                         第04期
作者: terse    时间: 2013-6-1 14:03

这种情况只有最后行才有吧
你想什么样目的  实在没理解

再说不被整除总是有空列的啊
作者: pan528    时间: 2013-6-1 20:50

回复 2# terse

把目录行索引切分为目录列索引,就是把一列的索引切成多列的索引,目的是使索引占用页面空间更小,更便于阅读。
可能出现多种情形。
为了讨论方便,设总行数=k,切分列数=c,每列行数=x=k/c
切分后无非出现这几种情形:
1、k/c=整数,不用添加空格,按x列直接导出索引即可;
2、k/c≠整数,即有余数,这有二种情形:
1)c<x,可直接在最后一列补空格,使每列对齐,这符合一般的阅读习惯,这种情形是绝大多数;
2)c≥x,如34行切成11列,34/11=3,余3。
这时c=x,排列时,前三列每列四行,其余8列只能每列三行另加一外空格才对齐。如果空格补在最后的列,最后二列就成了空列,看起来就少了二列,或者说只有9列了。
因此,c≥x,如果空都补在后面,也可能出现最后二列,甚至更多列都为空。不只是“最后行才有”。
作者: CrLf    时间: 2013-6-1 21:13

貌似是这样:
  1. @echo off
  2. set /a 列数=5,列宽=32
  3. %1 %0 :|more /t%列宽% >b.txt&pause&exit
  4. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  5. (for /f "delims=" %%a in (a.txt) do (
  6.    set str=%%a
  7.    setlocal enabledelayedexpansion
  8.    set /p=!str!%tab%
  9.    endlocal
  10.    set /a n+=1,n%%=列数,n/n||echo;
  11. ))<nul 2>nul
复制代码

作者: pan528    时间: 2013-6-1 22:20

回复 4# CrLf

谢谢回贴。但,这个代码有二点不是完全符合我的要求:
1、不是横排生成列,要竖排,顺序要先排第一列,再排第二列 ... 这样才比较符合阅读习惯,如下图:

以复杂一些的索引实例,会准确一些的表达我的意图。

2、不能整除,空格最好添加在最后一列,如上图。遇到特殊情形,才考虑在余数列的最后添加一个空格。
作者: terse    时间: 2013-6-2 00:12

汗  终于有点明白 楼主的意图  如是这样 缺失部分 空在右边?
作者: terse    时间: 2013-6-2 01:00

要使排版整齐
方案1 插人跳格 但行字符相差数 且中文 数字混合
方案2 找出最长字符行 按此行字符数排列  也有 中文 数字混合 干扰
方案3 找出最长字节行 按此行字节数排列
作者: CrLf    时间: 2013-6-2 02:32

  1. @echo off&setlocal enabledelayedexpansion
  2. set /a 列数=3,列宽=32
  3. %1 %0 :|more /t%列宽% >b.txt&pause&exit
  4. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  5. (for /f "delims=" %%a in (a.txt) do set /a n+=1&set /p ar[!n!]=)<a.txt
  6. set /a 行数=(n+列数-1)/ 列数
  7. for /l %%a in (1 1 %行数%) do (
  8. set "str="
  9. for /l %%b in (%%a %行数% %n%) do (
  10. set "str=!str!!ar[%%b]!%tab%"
  11. )
  12. echo;!str!
  13. )
复制代码

作者: pan528    时间: 2013-6-2 09:07

本帖最后由 pan528 于 2013-6-2 09:46 编辑

回复 8# CrLf

谢谢,这个代码解决了竖排和“c<x”的问题,但:
1、c≥x时,如34行切成11列,就会出现空列。
2、最后一列的空格是多余的,如果在网页显示上会被挤出一列,即多出一个空列,因此,最好能在最后一列不加空格。
作者: CrLf    时间: 2013-6-3 18:21

头绪比较乱,找不到合适的数学模型,坐等高人
作者: xxpinqz    时间: 2013-6-3 19:39

做目录索引是为了更方便快捷的的查找定位,排成这样感觉比原始的还不直观。数据多点比一列下来还难找。
关于最后一列的TAB被扩展的问题是否这样理解:
引自8楼Crlf代码:
  1. @echo off&setlocal enabledelayedexpansion
  2. set /a 列数=3,列宽=32
  3. %1 %0 :|more /t%列宽% >$&(for /f "tokens=*" %%a in ($) do echo %%a)>b.txt&del $&exit
  4. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  5. (for /f "delims=" %%a in (a.txt) do set /a n+=1&set /p ar[!n!]=)<a.txt
  6. set /a 行数=(n+列数-1)/ 列数
  7. for /l %%a in (1 1 %行数%) do (
  8.         set "str="
  9.         for /l %%b in (%%a %行数% %n%) do (
  10.                 set "str=!str!%tab%!ar[%%b]!"
  11.         )
  12.         echo;!str!
  13. )
复制代码
话说回来了,set /a 行数=(n+列数-1)/ 列数
这句太牛了,数学没及格过的人飘过......
作者: terse    时间: 2013-6-4 00:08

for 放在下面 可以省掉临时文件
作者: pan528    时间: 2013-6-4 22:53

回复 11# xxpinqz

谢谢!你这个代码又进了一步,最后一列的空格被取消了。但:
当c≥x时,如34行切成11列、12行切成5列,就会出现空列。

切分涉及到一些数学问题。
我想这里还有是采用二分法还是三分法的问题。

数学问题我不是很懂,可否这样考虑:
设总行数=k,切分列数=c,每列行数=x=k/c,余数=y
切分后无非出现这几种情形:
1、k/c=整数,不用添加空格,按x列直接导出索引即可;
2、k/c≠整数,即有余数,这有二种情形:
1)c<x,可直接在最后一列补空格,使每列对齐,这符合一般的阅读习惯,这种情形是绝大多数;
2)c≥x,如34行切成11列,34/11=3,余3。
这时c=x,排列时,前三列每列四行,其余8列只能每列三行另加一外空格才对齐。如果空格补在最后的列,最后二列就成了空列,看起来就少了二列,或者说只有9列了。

如果切分用二分法:
即:
k/c=整数时,直接切分。
k/c≠整数时,c-y列直接切分,y列每列加一空行。

如果切分用三分法:
即:
k/c=整数时,直接切分。
c<x时,直接在最后一列补空格。
c≥x时,c-y列直接切分,y列每列加一空行。

二分法切分要简单一些,三分法实际把“c≥x”作为特殊情况,另分一次。
因为特殊情况很少,所以三分法会更符合阅读习惯。
作者: terse    时间: 2013-6-4 23:47

楼主到底想要什么 我理解问题吗
是想余数为0吗?
不要说2分 N分
能简单举几个例及你认为的特殊情况 怎么排列最好 你最后的理想结果是什么
作者: terse    时间: 2013-6-4 23:52

如你所说 34行切成11列 在你看来特殊的
那你理想排列是怎样的呢
  1. 1行 5行  9行 13行 17行 21行 25行 29行 33行
  2. 2行 6行 10行 14行 18行 22行 26行 30行 34行
  3. 3行 7行 11行 15行 19行 23行 27行 31行
  4. 4行 8行 12行 16行 20行 24行 28行 32行
复制代码

作者: pan528    时间: 2013-6-5 08:29

回复 15# terse

我想要的是一个切分程序,总行数和要切分的列数是不定的,这样程序就有通用性。
我想这个程序首先要解决数学问题,我在一楼、三楼、十三楼分别说到了一些。如果要枚举,我在一楼已举了三个例子。其中“切分为五列”在最后一列补空,是比较符合阅读习惯的方法。其实,这个例子也可以从第二列开始,每列补一个空。如果对所有不能整除的总行数,只采用“每列补一个空”的方法,我称它为“二分法”,如果只对特殊情形“c≥x”(切分的列大于或等于切分后每列的行数)时,才用这种方法,其他的只在最后一列补空,我称它为“三分法”。

再说特殊例子:34行切成11列。
如果对这个例子只对最后一列补空行,就会成为你所列的情况。即:只能看到九列,其他二行不见了!这就是特殊情形!
对这种情况要分成十一列,只能采用对所有不能整除的总行数,用“每列补一个空”的方法来完成!

如下:
1行 5行  8行 11行 14行 17行 20行 23行 26行 29行 32行
2行 6行  9行 12行 15行 18行 21行 24行 27行 30行 33行
3行 7行 10行 13行 16行 19行 22行 25行 28行 31行 34行
4行

我的表达不标准,不知道你听明白了没有?
作者: xxpinqz    时间: 2013-6-5 12:10

回复 13# pan528
仔细看了一遍,感觉还是像天书般的深奥难懂
下面两句引自你的原文:
2)c≥x,如34行切成11列,34/11=3,余3。
这时c=x,排列时,前三列每列四行,其余8列只能每列三行另加一外空格才对齐。

这是什么算法能得出(c=x):34/11=11,接着还能得出余数是3.
看了一楼例子有点概念了,看了文字说明又糊涂了,要参考你哪个说法呢?没概念!!!

理解楼主好意想尽力表述清晰并提供一定的思路参考,但是生搬硬套的定义一个新概念并要强制灌输给看的人,好像并不是什么好办法。
鉴于目前好像都没人表示看的懂你的意思,你为什么不像一楼那样举个例子,辅以你所说的3种情况分别按15楼terse那样的排版手段列出需要的排版结果呢。

别人能写则写,写了你也就不用去管别人到底是用加减法还是乘除法或者N分法
作者: terse    时间: 2013-6-5 13:53

唉 ~  终于有个大致算法  看还有什么变数
作者: xxpinqz    时间: 2013-6-5 14:33

  1. 当文档总行数=26,列数c=5,每列行数x=5,余数=1时
  2. 即:c≥x时,按你15楼理解应该排成这样:(前余数=1列为x+1=6行,后面剩余的列按x行)
  3. 1    7    12   17   22
  4. 2    8    13   18   23
  5. 3    9    14   19   24
  6. 4    10   15   20   25
  7. 5    11   16   21   26
  8. 6
  9. 但是1楼给出的却是:
  10. 当文档总行数=26,列数c=5,每列行数x=5,余数=1时
  11. 1    7    13   19   25
  12. 2    8    14   20   26
  13. 3    9    15   21
  14. 4    10   16   22
  15. 5    11   17   23
  16. 6    12   18   24
  17. 同理当文档总行数=26,列数c=7,每列行数x=3,余数=5时,此时c≥x是应是按以下排版,可对?:
  18. 1    5    9    13   17   21   24
  19. 2    6    10   14   18   22   25
  20. 3    7    11   15   19   23   26
  21. 4    8    12   16   20
  22. 所以按你文字说明,下面的情况应该是按下面前者而非后者,可对?
  23. 当文档总行数=26,列数c=4,每列行数x=6,余数=2时,c<x,这样排:
  24. 1    8    15   22
  25. 2    9    16   23
  26. 3    10   17   24
  27. 4    11   18   25
  28. 5    12   19   26
  29. 6    13   20
  30. 7    14   21
  31. 当文档总行数=26,列数c=4,每列行数x=6,余数=2时,c<x,而非这样排:
  32. 1    8    15   21
  33. 2    9    16   22
  34. 3    10   17   23
  35. 4    11   18   24
  36. 5    12   19   25
  37. 6    13   20   26
  38. 7    14
  39. 如果上面理解正确,那么12/5,34/11,28/9则均属于c>x的情况,即按你15楼给出的(前余数列为x+1行,后面剩余列按x行)
  40. 这有什么特殊呢?
  41. 如果我的描述有误,你就以26行为例,把分割成3,4,5,6,7列的结果排上来看看。整除的就不用了。
  42. 然后把正确描述更新到顶楼吧,目前描述的错误蛮多的。
  43. 草拟了一个代码,不过好像有点繁杂了,等着看看terse的算法...
复制代码

作者: terse    时间: 2013-6-5 14:41

不知道是否应该是这个意图
我猜的
  1. @echo off&setlocal enabledelayedexpansion
  2. set L=11
  3. set "file=test.txt"
  4. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  5. for /f "usebackq tokens=*" %%i in ("%file%") do set /a N+=1&set #!N!=%%i
  6. set /a h=(n+l-1)/l,j=(n%%l)*H,i=h-1
  7. if !j! leq 0 set j=n
  8. for /l %%i in (1 1 %n%) do (
  9.     if %%i leq %j% (
  10.        set /a "m=(%%i-1)%%h+1"
  11.     ) else set /a "m=-~%%i %% i+1"
  12.       for %%j in (!m!) do set "$%%j=!$%%j!%tab%!#%%i!"
  13. )
  14. (for /l %%i in (1 1 %h%) do for /f "tokens=*" %%j in ("!$%%i!") do echo %%j)>$T.em
  15. more /t16 $T.em >n.txt
  16. del $T.em
  17. pause
复制代码

作者: xxpinqz    时间: 2013-6-5 18:14

呵呵,大家都用猜的~,把CrLf代码改改成这样。
  1. @echo off&setlocal enabledelayedexpansion
  2. rem 生成测试文件
  3. (for /l %%a in (1,1,26) do echo %%a)>$1
  4. rem 以下主体部分
  5. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  6. (for /f "delims=" %%a in ($1) do set /a n+=1&set /p ar[!n!]=)<$1
  7. set /a 列数=5,列宽=5,m=n/列数,余数=n%%列数,行数=(n+列数-1)/列数,修正递增=行数-1,修正终值=行数*余数
  8. if !修正终值! neq 0 (
  9.   set 有余数=.
  10.   if %列数% leq %m% set /a 修正终值="(列数-1)*行数"
  11.   call :sc "!修正终值!"
  12. ) else (
  13.   call :sc "!n!"
  14. )
  15. more /t%列宽% $t>b.txt
  16. del $?&start b.txt&exit /b
  17. :sc
  18. set /a a=c=行数,b=0,d=%~1
  19. :loop
  20. for /l %%a in (1 1 %a%) do (
  21.     set /a b+=1
  22.     for /l %%b in (!b! %c% %d%) do (
  23.       if "!str%%a!"=="" (
  24.         set "str%%a=!ar[%%b]!"
  25.       ) else (
  26.         set "str%%a=!str%%a!%tab%!ar[%%b]!"
  27.       )
  28.     )
  29. )
  30. if defined 有余数 (
  31.     set /a a=行数-1,b=修正终值,c=修正递增,d=n
  32.     set "有余数="
  33.     goto :loop
  34. )
  35. (
  36. echo 当文档总行数=%n%,列数c=%列数%,每列行数x=%m%,余数=%余数%时
  37. if !列数! leq !m! (echo 即c小于等于x) else echo 即c大于x
  38. for /l %%a in (1,1,%行数%) do echo,!str%%a!
  39. )>$t
  40. goto :eof
复制代码

作者: pan528    时间: 2013-6-5 18:50

回复 17# xxpinqz

请原谅,是我粗心。
“这时c=x,排列时,前三列每列四行,其余8列只能每列三行另加一外空格才对齐。”这句算错了。
应为:“这时c=x,排列时,前一列每列四行,其余10列只能每列三行另加一外空格才对齐。”
作者: pan528    时间: 2013-6-5 18:52

回复 21# xxpinqz
谢谢!终于有了三分法的切分程序。
慢慢消化,学习学习。
作者: pan528    时间: 2013-6-5 18:57

回复 20# terse

是一个二分法的切分程序。
通过了34/11的情况,但 34/4时,就出错了,第三列和第四列顺序都出错了,结果如下:
1               10              23              31
2               11              24              32
3               12              25              33
4               13              26              34
5               14              19              27
6               15              20              28
7               16              21              29
8               17              22              30
9               18
作者: xxpinqz    时间: 2013-6-5 19:34

是21楼代码那样的效果?
呵呵,晕倒,一句话能交代清楚的问题,被你天书般的描述弄的大家头都晕了。
作者: terse    时间: 2013-6-5 20:13

还是计算错了 这个也只是简单测试
  1. @echo off&setlocal enabledelayedexpansion
  2. set L=5
  3. set "file=a.txt"
  4. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  5. for /f "usebackq tokens=*" %%i in ("%file%") do set /a N+=1&set #!N!=%%i
  6. set /a h=(n+l-1)/l,j=(n%%l)*H,_i=h-1
  7. if !j! leq 0 set j=n
  8. for /l %%i in (1 1 %n%) do (
  9.     if %%i leq %j% (
  10.        set /a "m=(%%i-1)%%h+1"
  11.     ) else set /a "m=(%%i--~j)%%_i+1"
  12.       for %%j in (!m!) do set "$%%j=!$%%j!%tab%!#%%i!"
  13. )
  14. (for /l %%i in (1 1 %h%) do for /f "tokens=*" %%j in ("!$%%i!") do echo %%j)>csm.txt
  15. more /t16 csm.txt >nmn.txt
  16. pause
复制代码

作者: terse    时间: 2013-6-5 20:15

现在楼主的意图出来了 算是理解了
作者: pan528    时间: 2013-6-5 20:44

本帖最后由 pan528 于 2013-6-5 20:46 编辑

回复 26# terse

测试通过!代码挺精炼的。如果能改成三分法就更完美了。谢谢!

能解释一下,下面代码的含义吗?

for /f "delims=U" %%a in ('cmd /u /c echo 唉') do
作者: terse    时间: 2013-6-5 20:55

你所谓的 3分法  是什么样的分法
上面取得跳格键
作者: pan528    时间: 2013-6-5 21:10

回复 29# terse

三分法就是:在上面二分法的基础上,对切分列数小于每列行数的情形,用另一种方法排列,即把所有空格放在最后一列。
比如:
二分法:
1        10        19        27
2        11        20        28
3        12        21        29
4        13        22        30
5        14        23        31
6        15        24        32
7        16        25        33
8        17        26        34
9        18
三分法
1    10   19   28
2    11   20   29
3    12   21   30
4    13   22   31
5    14   23   32
6    15   24   33
7    16   25   34
8    17   26
9    18   27
作者: terse    时间: 2013-6-5 21:18

我的理解  前面几个应该就是 你所谓的3分法吧
作者: pan528    时间: 2013-6-5 22:33

回复 31# terse

二十一楼就是三分法。
作者: xxpinqz    时间: 2013-6-5 22:37

按我理解,就是下面这意思:
假设总行数n,列数l,则行数h=n/l,余数y=n%%l
一、当余数y=0,则直接输出。
二、  余数y>0,则:
                1、l大于h,则前y列各加一行为h+1,后l-y列为h行
                2、l小于等于h,则前l-1列各加一行为h+1,余者为最后一列即n-(l-1)*(h+1)行

改下代码半小时不到,理解楼主的意思花了两天最后还是靠瞎猜出来的。
作者: pan528    时间: 2013-6-5 22:41

回复 33# xxpinqz

是这个意思。但我没有按写程序的方式来表达,让你费心了。请原谅。
作者: terse    时间: 2013-6-5 22:44

回复 34# pan528
难道 我26楼代码 只能2分或者3分吗?
应该两则都兼容
作者: pan528    时间: 2013-6-5 22:50

回复 35# terse


我试了一下,26楼的代码只能二分法,21楼的代码是三分法。
作者: terse    时间: 2013-6-5 22:55

回复 36# pan528
26楼代码 将if !j! leq 0 set j=n  改 set j=n 试下
应该这样了
作者: CrLf    时间: 2013-6-6 02:32

我早先是靠测试弄懂了楼主的规则,但是没有好的思路,想法太繁琐,应该有更好的就题解题算法,目测 plp626 能手到擒来
作者: terse    时间: 2013-6-6 11:47

我目前 最直观的解  set /a 行=(总行+列-1)/列,余=(总行%%列)*行
得到 行 和 余的值
只要在 FOR 循环  判断总行 和 余 关系 应该够解了吧
作者: xxpinqz    时间: 2013-6-6 12:50

回复 39# terse
话说我的数学就是加减乘除 ,所以算法吃不透,目测26楼代码是按输完一列再接着输下一列的按顺序输出
所以判断是否所谓三分也应该要用n/l来判断,而非0。
扯了3页,就下面两句是亮点:
8楼的set /a 行数=(n+列数-1)/ 列数
26楼的set /a "m=(%%i--~j)%%_i+1"
向两位高手致敬~~
作者: terse    时间: 2013-6-6 13:33

回复 40# xxpinqz
再仔细回看前面 猜真这次应该理解了
先粗糙一个
感觉代码写得太啰嗦   等下再看有 优化的可能不
  1. @echo off&setlocal enabledelayedexpansion
  2. %1 %0 REM|more /t32 >n.txt
  3. set L=5
  4. set "file=a1.txt"
  5. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  6. for /f "usebackq tokens=*" %%i in ("%file%") do set /a N+=1&set #!N!=%%i
  7. set /a h=(n+l-1)/l,j=n,i=1
  8. if !h! lss !l! set /a j=(n%%l)*H
  9. for /l %%i in (1 1 %n%) do (
  10.     set /a "t=^!^!(~-%%i/j)"
  11.     set /a "m=(~-%%i-(t*j))%%(~-H+i*^!t)+1"
  12.     for %%j in (!m!) do set "$%%j=!$%%j!%tab%!#%%i!"
  13. )
  14. for /l %%i in (1 1 %h%) do for /f "tokens=*" %%j in ("!$%%i!") do echo %%j
复制代码

作者: terse    时间: 2013-6-6 13:36

唉 惭愧我的理解力  但楼主的表达也太那个了  
都和我一样 国语学得不好
作者: pan528    时间: 2013-6-6 16:51

回复 41# terse

测试通过!是三分法。不过最后多了一个回车,不知问题出在哪?
作者: terse    时间: 2013-6-6 23:36

你是指最后的回车行是MORE留下的吧
代码再少点变量
另补上exit
  1. @echo off&setlocal enabledelayedexpansion
  2. %1 %0 :|more /t32 >n.txt&exit
  3. set L=9
  4. set "file=a.txt"
  5. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  6. for /f "usebackq tokens=*" %%i in ("%file%") do set /a N+=1&set #!N!=%%i
  7. set /a h=(n+l-1)/l,j=n
  8. if !h! lss !l! set /a j=(n%%l)*h
  9. for /l %%i in (1 1 %n%) do (
  10.     set /a "i=^!(~-%%i/j),m=(~-%%i-(^!i*j))%%(~-H+i)+1"
  11.     for %%j in (!m!) do set "$%%j=!$%%j!%tab%!#%%i!"
  12. )
  13. for /l %%i in (1 1 %h%) do for /f "tokens=*" %%j in ("!$%%i!") do echo %%j
复制代码

作者: pan528    时间: 2013-6-7 21:11

回复 44# terse

回车没有剔除,我还发现一个新问题:所有代码在34/9时都变成了二分法!即:
1    5    9    13   17   21   25   29   32
2    6    10   14   18   22   26   30   33
3    7    11   15   19   23   27   31   34
4    8    12   16   20   24   28
而三分法应为:
1    5    9    13   17   21   25   29   33
2    6    10   14   18   22   26   30   34
3    7    11   15   19   23   27   31
4    8    12   16   20   24   28   32
我怀疑是算法有问题。
各位高手找找原因吧。
作者: pan528    时间: 2013-6-7 21:25

你们的代码太精炼了,我许多方面都没有看明白。
我以前写了一个切分文本的代码,很菜。代码很长,很繁琐,方法也简单,拿出来请各位高手改改。
但,我试过好多次,没有出错过。
  1. :: 代码代号含义:
  2. :: k=文本总行数
  3. :: cut=切分的列数
  4. :: x=k/c=每列的行数
  5. :: r=remainder=余数行=k-cx
  6. :: ak=总添加的行数=(cut*(x+1))-k
  7. :: s=记录当前文件需要排列的行数=x或(x+1)
  8. :: s2=少行列=s-ak
  9. :: n=记录当前列输出到第几行
  10. :: m=记录当前输出到第几个文件
  11. @echo off
  12. title 切分文本程序(三分法)
  13. set file=a
  14. set Cut=9
  15. setlocal enabledelayedexpansion
  16. for /f "delims=" %%a in (%file%.txt) do set/a k+=1
  17. set /a x=%k%/%Cut%
  18. set /a r=%k%-%Cut%*%x%
  19. set /a ak=(%Cut%*(%x%+1))-%k%
  20. set m=
  21. set m=1
  22. set n=
  23. for /f "delims=" %%i in (%file%.txt) do (
  24. set /a n+=1
  25. if !r! leq 0 (
  26. set /a s=%x%
  27. if !n! leq !s! echo %%i>>%file%_!m!.txt
  28. if !n! equ !s! set n=0 & set /a m+=1
  29. ) else (
  30. set /a s=%x%+1
  31. if !ak! lss !s! (
  32. if !n! leq !s! echo %%i>>%file%_!m!.txt
  33. if !n! equ !s! set n=0 & set /a m+=1
  34. if !m! equ !cut! set /a s2=!s!-!ak!
  35. if !n! equ !s2! for /l %%i in (1,1,%ak%) do echo.>>%file%_!cut!.txt
  36. ) else (
  37. if !m! leq !r! (
  38. if !n! leq !s! echo %%i>>%file%_!m!.txt
  39. if !n! equ !s! set n=0 & set /a m+=1
  40. ) else (
  41. if !m! gtr !r! if !n! leq !x! echo %%i>>%file%_!m!.txt
  42. if !m! gtr !r! if !n! equ !x! echo.>>%file%_!m!.txt
  43. if !n! equ !x! set n=0 & set /a m+=1
  44. )
  45. )
  46. )
  47. )
  48. endlocal
  49. goto:eof
复制代码

作者: terse    时间: 2013-6-7 22:10

回复 30# pan528
也许代码的算法有误
这样吧 你把44楼代码里  if !h! lss !l! set /a j=(n%%l)*h 这里的 LSS 改为GTR 看是否你要的
  1. @echo off&setlocal enabledelayedexpansion
  2. %1 %0 :|more /t32 >n.txt&exit
  3. set L=9
  4. set "file=test.txt"
  5. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  6. for /f "usebackq tokens=*" %%i in ("%file%") do set /a N+=1&set #!N!=%%i
  7. set /a h=(n+l-1)/l
  8. if !h! gtr !l! set /a j=(n%%l)*h
  9. if !j! equ 0 set j=!n!
  10. for /l %%i in (1 1 %n%) do (
  11.     set /a "i=^!(~-%%i/j),m=(~-%%i-(^!i*j))%%(~-H+i)+1"
  12.     for %%j in (!m!) do set "$%%j=!$%%j!%tab%!#%%i!"
  13. )
  14. for /l %%i in (1 1 %h%) do for /f "tokens=*" %%j in ("!$%%i!") do echo %%j
复制代码
代码处理流程是这样的
当行大于列 或 行小于列时的输出是不一样的
作者: pan528    时间: 2013-6-7 22:23

回复 47# terse

34/9通过了,34/11又变成了9列,我想算法可能有缺陷或漏洞 ...
作者: terse    时间: 2013-6-8 11:24

本帖最后由 terse 于 2013-6-8 14:10 编辑

有点给数字绕晕的感觉
只能再试着简化下 思路闭塞 总不能突破
  1. @echo off&setlocal enabledelayedexpansion
  2. %1 %0 :|more /t32 >n.txt&exit
  3. set "file=test.txt"
  4. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  5. for /f "usebackq tokens=*" %%i in ("%file%") do set /a N+=1&set #!N!=%%i
  6. set L=9
  7. set /a "h=(n+l-1)/l,i=^!(~-l/h),j=^!i*(n%%l)*h+i*n"
  8. for /l %%i in (1 1 !n!) do (
  9.     set /a "i=^!(~-%%i/j),m=(~-%%i-(^!i*j))%%(~-h+i)+1"
  10.     for %%j in (!m!) do set "$%%j=!$%%j!%tab%!#%%i!"
  11. )
  12. for /l %%i in (1 1 !h!) do for /f "tokens=*" %%j in ("!$%%i!") do echo %%j
复制代码
既然MORE 最后回车肯定有 没必要再处理它了吧
  1. @echo off&setlocal enabledelayedexpansion
  2. %1 %0 :|more /t32 >n.txt&exit
  3. set "file=test.txt"
  4. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  5. for /f "usebackq tokens=*" %%i in ("%file%") do set /a N+=1&set #!N!=%%i
  6. set L=9
  7. set /a "h=(n+l-1)/l,j=n%%l,i=^!(l/h)"
  8. if !j! equ 0 (set j=!n!)else set /a "j=~-l*h*i+j*h"
  9. for /l %%i in (1 1 !n!) do (
  10.     set /a "i=^!(~-%%i/j),m=(~-%%i-(^!i*j))%%(~-h+i)+1"
  11.     for %%j in (!m!) do set "$%%j=!$%%j!%tab%!#%%i!"
  12. )
  13. for /l %%i in (1 1 !h!) do for /f "tokens=*" %%j in ("!$%%i!") do echo %%j
复制代码

作者: pan528    时间: 2013-6-9 22:53

回复 49# terse
34/11,34/9都通过了,但是仍二分法,不是三分法:

二分法:
1       5       9       13      17      21      25      29      32
2       6       10      14      18      22      26      30      33
3       7       11      15      19      23      27      31      34
4       8       12      16      20      24      28

三分法:(余数小于每列的行数时,空行全部放在最后一列)
1       5       9       13      17      21      25      29      33
2       6       10      14      18      22      26      30      34
3       7       11      15      19      23      27      31
4       8       12      16      20      24      28      32
作者: terse    时间: 2013-6-9 23:34

本帖最后由 terse 于 2013-6-9 23:36 编辑

不是列大于行 3分吗
余数: 34/9 应该余7  7大于行4啊
这里的余数是否 应该  34/4 余 2 ?

你30楼的描述
..三分法就是:在上面二分法的基础上,对切分列数小于每列行数的情形,用另一种方法排列,即把所有空格放在最后一列。...





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