[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

成绩单排序(多条件)挑战

本帖最后由 ivor 于 2019-6-1 10:00 编辑

同时满足以下条件:
1.语文升序
2.数学降序
3.英语升序
4.化学降序
5.生物升序

每一行的数据不能改变,排序最小单位是行,条件是列

不限制语言,数据约1w条。1秒内

样本:
语文 数学 英语 化学 生物
79 77 70 77 67
64 70 74 75 72
79 64 72 62 76
62 75 65 71 63
79 76 62 62 77
66 63 77 75 79
74 75 72 61 61
71 63 79 60 70
74 64 74 78 69


抛砖引玉
  1. GC "1.txt"  | select @{name='语文'; expression={$_.split(" ")[0]}},
  2. @{name='数学'; expression={$_.split(" ")[1]}},
  3. @{name='英语'; expression={$_.split(" ")[2]}},
  4. @{name='化学'; expression={$_.split(" ")[3]}},
  5. @{name='生物'; expression={$_.split(" ")[4]}} | `
  6. Sort-Object -Property @{Expression = {$_.语文}; Ascending = $true},
  7. @{Expression = {$_.数学}; Ascending = $false},
  8. @{Expression = {$_.英语}; Ascending = $true},
  9. @{Expression = {$_.化学}; Ascending = $false},
  10. @{Expression = {$_.生物}; Ascending = $true}
复制代码
1

评分人数

  1. use Encode;
  2. use File::Slurp;
  3. STDOUT->autoflush(1);
  4. my @lines = read_file("src.txt");
  5. my $head = shift @lines;
  6. my @mat = map { s/\r?\n$//; [split " ", $_]; } @lines;
  7. @mat = sort {
  8.     $a->[0] <=> $b->[0] ||
  9.     $b->[1] <=> $a->[1] ||
  10.     $a->[2] <=> $b->[2] ||
  11.     $b->[3] <=> $a->[3] ||
  12.     $a->[4] <=> $b->[4]
  13. } @mat;
  14. grep { printf "%s\n", join(",", @$_); } @mat;
复制代码
  1. 62,75,65,71,63
  2. 64,70,74,75,72
  3. 66,63,77,75,79
  4. 71,63,79,60,70
  5. 74,75,72,61,61
  6. 74,64,74,78,69
  7. 79,77,70,77,67
  8. 79,76,62,62,77
  9. 79,64,72,62,76
复制代码
不知道理解的对不对,升降升降升,分级排序。
1

评分人数

    • ivor: 学习了技术 + 1

TOP

本帖最后由 xczxczxcz 于 2019-5-31 06:54 编辑

把你的数据复制粘贴了15363多条,耗时 1.06秒。

修改了一下返回值: 现在 0.8秒。

再试试C#.
用VSCODE  写C#  编译结果15ms  输出到文本24ms。VS2019 编译 27ms  写入文本56ms。
1

评分人数

    • ivor: 代码呢技术 + 1

TOP

有种使用excel的冲动
1

评分人数

    • ivor: 我就是从Excel想出来的这个问题。技术 + 1

TOP

  1. var fso = new ActiveXObject('Scripting.FileSystemObject');
  2. var txt = fso.OpenTextFile('1.txt', 1).ReadAll();
  3. var arr = txt.replace(/^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)(?:\r\n|$)/mg,
  4.     function(s0, s1, s2, s3, s4, s5){
  5.         return 100 + 1*s1 + '' + (200 - s2) + '' + (100 + 1*s3) + '' + (200 - s4) + '' + (100 + 1*s5) + ' ' + s0;
  6.     }
  7. ).split(/\r\n/).sort();
  8. fso.OpenTextFile('2.txt', 2, true).Write(arr.join('\r\n').replace(/^\d+ /mg, ''));
复制代码
1

评分人数

TOP

  1. $Code = @"
  2.     using System;
  3.     using System.Linq;
  4.     using System.Text.RegularExpressions;
  5.     using System.Collections.Generic;
  6.     public static class Program {
  7.         public static IEnumerable<string> Run(string[] lines) {
  8.             var query = from line in lines
  9.                         let m = Regex.Match(line, @"^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$")
  10.                         where m.Success == true
  11.                         orderby int.Parse(m.Groups[1].Value), int.Parse(m.Groups[2].Value) descending, int.Parse(m.Groups[3].Value),
  12.                                 int.Parse(m.Groups[4].Value) descending, int.Parse(m.Groups[5].Value)
  13.                         select line;
  14.             return query;
  15.         }
  16.     }
  17. "@;
  18. Add-Type -TypeDefinition $Code;
  19. $arr = [IO.File]::ReadAllLines('1.txt');
  20. [IO.File]::WriteAllLines('2.txt', [Program]::Run($arr));
  21. pause
复制代码
1

评分人数

    • ivor: 结果正确,速度最快技术 + 1

TOP

用bat对付一万行的数据,到1.4秒貌似下不去了:
  1. @echo off & setlocal enabledelayedexpansion
  2. echo %time% - 开始
  3. for /l %%a in (0 1 99) do (
  4. set /a B=10%%a,L=200-%%a
  5. set B%%a=!B:~-2!
  6. set L%%a=!L:~-2!
  7. )
  8. set B100=xx
  9. set L100=--
  10. echo %time% - 构建映射表
  11. (for /f "skip=1 tokens=1-5" %%a in (test.txt) do (
  12. echo !B%%a!!L%%b!!B%%c!!L%%d!!B%%e! %%a %%b %%c %%d %%e
  13. ))>tmp.txt
  14. echo %time% - 输出临时文件
  15. (echo 语文 数学 英语 化学 生物
  16. for /f "tokens=1*" %%a in ('sort tmp.txt') do echo %%b
  17. )>out.txt
  18. echo %time% - 结束
  19. pause & exit /b
复制代码
附测试数据生成脚本
  1. @echo off & setlocal enabledelayedexpansion
  2. (echo 语文 数学 英语 化学 生物
  3. for /l %%a in (1 1 10000) do (
  4. set /a R1=!random!%%101,R2=!random!%%101,R3=!random!%%101,R4=!random!%%101,R5=!random!%%101
  5. echo !R1! !R2! !R3! !R4! !R5!
  6. ))>test.txt
  7. pause
复制代码

TOP

回复 7# CrLf


    结果不正确,少一行数据

TOP

加糖,类似5楼操作。
pack - "C"  An unsigned char (octet) value.
打包后的数据是字节对齐的。
  1. use File::Slurp;
  2. STDOUT->autoflush(1);
  3. my @lines = read_file("src.txt");
  4. my $head = shift @lines;
  5. grep {
  6.     my $it = 0;
  7.     printf "%s\n", join(",", map { $it++%2 ? 100-$_ : $_ } unpack("C*", $_));
  8. } sort map {
  9.         my $it = 0;
  10.         s/\r?\n$//;
  11.         pack("C*", map { $it++%2 ? 100-$_ : $_ } split " ", $_);
  12.     } @lines;
复制代码

TOP

本帖最后由 523066680 于 2019-6-2 07:50 编辑

PS+C Sharp 处理1W行具体时间是多少, 不懂PS 和 C Sharp

在网上找了一下 时间获取方法:
  1. $start = Get-Date
  2. # 中间代码
  3. $end = Get-Date
  4. Write-Host -ForegroundColor Red ('Total Runtime: ' + ($end - $start).TotalSeconds)
复制代码
Total Runtime: 0.1280073

perl pack 字节流方案  0.08 秒

去掉 unpack 改为按数组索引处理
  1. use File::Slurp;
  2. use Time::HiRes qw/time/;
  3. my $ta = time();
  4. my @lines = read_file("test.txt");
  5. my $head = shift @lines;
  6. my $buff = "";
  7. my @dupl = map {
  8.     my $it = 0;
  9.     s/\r?\n$//;
  10.     pack("C*", map { $it++%2 ? 100-$_ : $_ } split " ", $_);
  11. } @lines;
  12. my @idx = sort { $dupl[$a] cmp $dupl[$b] } (0..$#dupl);
  13. grep { $buff .= $lines[$_] ."\r\n" } @idx;
  14. write_file("pl_out.txt", {binmode=>"raw"}, $buff);
  15. printf "%.3f\n", time() - $ta;
复制代码
含文件输出 0.046s

2楼代码改文件输出 0.045s
1

评分人数

    • ivor: perl我不会,所以不知道时间,尴尬技术 + 1

TOP

回复 11# 523066680


    是的,如果非常在意零点几秒速度的话,这个问题用 PowerShell 来解不合适,甚至比不过 js 脚本。
但多一种解题思路总是好的,并且 PowerShell 功能强大,速度也不算慢。关键是用它能方便地解决问题,又是系统自带,我认为这就够了。

TOP

本帖最后由 523066680 于 2019-6-2 07:55 编辑

回复 12# WHY

    不在意秒,之前也未报时间。而是ivor写的 "最" 有一种钦定的意思,后面还有未发帖的人呢。ivor已经回复我了。

TOP

小白来个python版的:
  1. file = "test.txt"
  2. result = "res.txt"
  3. with open(file,"r",encoding="utf8") as f:
  4.     head = f.readline()    #读第一行头
  5.     gen = (tuple(int(x) for x in line.split()) for line in f)
  6.     res = sorted(gen,key=lambda x:(x[0],-x[1],x[2],-x[3],x[4]))  #多条件排序,取负值按降序
  7. with open(result,"w") as f:
  8.     f.write(head)         #写第一行头
  9.     for i in res:
  10.         f.write(" ".join(str(x) for x in i)) #拼接成字符串写入
  11.         f.write("\n")
复制代码
python性能肯定不是最快的,用了7楼CrLf生成的测试数据1W条,运行完成时间是0.33秒左右。

TOP

有种使用数据库的冲动
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 8# ivor


    skip=1跳过标题行了。测试数据不包含标题行吗?

TOP

返回列表