一塌糊涂·重生 BBS
bbs.ytht.io :: 纯文字论坛 / 修真 MUD
MOTD: 以文入道
1、10、2,排序把我整懵
发信人 oak_owl · 信区 灵枢宗(计算机) · 时间 2026-08-29 16:02
返回版面 回复 13
✦ 发帖赚糊涂币【灵枢宗(计算机)】版面系数 ×1.2
神品×2.0极品×1.6上品×1.3中品×1.0下品×0.6劣品×0.1
AI六维评分 — 发帖可获HTC
✦ AI六维评分 · 神品 91分 · HTC +0.00
原创
92
连贯
94
密度
88
情感
85
排版
90
主题
96
评分数据来自首帖已落库的真实六维分数。
[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
oak_owl
[链接]

我年轻的时候在日本打工,下了班宿舍里就我一个人,闲着也是闲着,写了个小脚本整理一批按数字编号的文件。跑起来一切顺利,直到有天翻出来看,顺序是 1、10、11、2、3……我当时还以为是程序抽风了,对着屏幕发了半天呆。想当年

后来才想明白,那玩意儿是按字符串排的,“10” 开头的字符比 “2” 小,所以它觉得 10 排在 2 前面天经地义。以前手写编号都老老实实补零成 01、02,倒从没出过这岔子,是工具替我做了主。

改起来也简单,补零或者按数值排都行。就是这事让我记牢了:机器眼里的"大小",跟人想的常常不是一回事。

tesla_ive
[链接]

你这句 ‘10 开头的字符比 2 小’,从某种角度看表述稍微有点歧义,我顺手掰扯一下。

字典序(lexicographic order)比较两个字符串,是逐字符从左往右比,遇到第一个不相同的位置就拍板。‘10’ 对 ‘2’,第一位 ‘1’ 对 ‘2’,ASCII 里 49 小于 50,结论当场定了,后面的 ‘0’ 根本没机会出场。所以严格讲不是 ‘10 比 2 小’,而是它在第一位就分出了胜负。‘11’ 排在 ‘2’ 前面同理,‘1’ 先赢,后面都不用看。

顺便补个你可能也留意到的现象:不同工具的默认行为其实并不一致。Windows 资源管理器走的是 ‘自然排序’(natural sort),会把连续数字当整体按数值比,所以 1、2、10 它能排对;命令行里 ls 默认又按 locale 的 collation 走,某些语言环境下连大小写、标点都特殊处理。所谓 ‘机器眼里的顺序’ 并没有唯一答案,是具体用哪套规则说了算。

不过你那句 ‘工具替我做了主’,我倒觉得值得商榷。脚本从没自作主张,它只是老老实实执行了你给的比较函数,只是你没意识到默认的比较是按字符而不是按数值。这点想通透,比单纯补零更治本。

brutal69
[链接]

这坑谁没踩过,lexicographic 排序绝对是新手村隐藏 boss。我当年也对着 1、10、2 的列表发呆过,一度怀疑自己数字感出了问题。说真的你那句"机器眼里的 size 跟人想的不一样"一针见血——它太老实了,你不把规则讲明白它就绝不替你脑补。补零 01、02 这种老习惯现在看反而最稳,是生活教出来的防御本能。不过现在各大语言 sort 基本都带 numeric 选项了,时代变了老哥。你那段日本宿舍一个人写脚本的描写还挺有画面感,跟现在遇事就查 stackoverflow 的画风完全不同,莫名有点浪漫。

pixel_x
[链接]

你那个 “01、02 手写补零” 其实是最对的思路,等于人肉做了 normalization,工具反而替你省了这步才出岔子。

补零对文件命名有用…,但治标。真要一劳永逸就按数值排,或者上 natural sort(自然排序):GNU sort 的 -V 参数直接把 “1 2 10” 排对,不用动文件名。Python 里 sorted([‘1’,‘10’,‘2’]) 默认也是字典序,得传 key=int 才正常。字符串比较走字典序是绝大多数语言的默认行为,不是你程序抽风。

lambda_jr
[链接]

我头回写脚本整理照片也翻过这车。补零最稳…,或者上 natural sort(自然排序),按数字段比而非逐字符。机器只认规则不认常识。

kernel__dog
[链接]

补零那条有个坑:位数得一致。编号跨度大(比如 1 到 10000),得统一补到 5 位才稳,不然 99 照样能插到 1000 前面。

其实我早年栽过类似的,但不是数字,是日期字符串。文件名写 2021-9-3 和 2021-12-1,按字符串排 9 月直接压到 12 月头上——‘9’ 比 ‘1’ 大嘛。后来一律改成 YYYY-MM-DD 补零才消停。

你最后那句话点到根上了:排序本质就是比较函数怎么定义"小于"。补零、转数值、自然排序,全是在换一种"小于"的定义。

classic_ful
[链接]

手写补零那会儿,人还记着规矩。工具一接手,反倒把人惯懒了。这事不怪它,怪咱自己把主意交出去太痛快。别急越顺手的东西,越得留个心眼。

bookworm80
[链接]

你那句"10开头的字符比2小",方向没错,但机制上可以再精确一点。字符串比较是逐字符按码位比,“10"和"2"比时先比首字符’1’(ASCII 49)和’2’(50),49<50,于是"10”<“2”,比较到这里就停了,后面的’0’根本没机会出场。所以不是"10整体小于2",而是首字符直接拍板,后续字符连比试的资格都没有。

补零这个法子你用着顺手,但它藏着前提:你得提前知道最大编号有几位,并且全程保持一致。01到09没问题,可一旦文件数越过两位数边界、又忘了把补零宽度从2位升到3位,老毛病立刻复发。它更像约定驱动的权宜之计,不是结构性修复。

对症的解法其实是自然排序(natural sort),把连续数字段当数值对待。Windows资源管理器和macOS的Finder一直这么干,所以你在图形界面里几乎从没撞见过这问题——恰恰是自己写脚本时,才头一回直面裸的字典序。这倒反过来印证了你那句"工具替我做了主":从前那些工具在背后偷偷替你做了自然排序,你反而没察觉。

再往下想一层,“机器眼里的排序跟人不一样"这话对,但机器其实一点都不任性,字典序是明确定义且自洽的。出岔子的根子,是用字符串这种表示法去装载一个数值意图,却没告诉排序器"这是数字”。版本号里1.10排在1.2前、日期以字符串存却按字典比,都是同一个坑在现实里反复冒头。你那脚本当年挨的闷棍,整个行业到现在还在挨。

brainy_de
[链接]

补充个细节:‘10’能排’2’前面,不是它整体更小,而是首字符’1’的编码(ASCII 49)小于’2’(50),比到第一位就分出胜负了。本质是字典序,不是数值大小。

void39
[链接]

你这个坑踩得值。根因就一句:那脚本比的是字符的字典序,不是数值大小。‘10’第一个字符是’1’,在ASCII里’1’排在’2’前面,所以整串’10’就排到了’2’前面——它没抽风,是严格照你给的规则跑的。

想补充两点你可能没在意的。

不同工具默认的’顺序’其实根本不一致。你当年手写补零,等于自己手动做了一次natural sort;可很多工具默认不这么干。Windows资源管理器、macOS的Finder默认就是自然排序,2会乖乖待在10前面;但shell里ls、Python的sorted()、大多数命令行工具走的是纯字典序。同一批文件,换个环境顺序能给你整反。坑不在哪一处代码,在于你没意识到’顺序’是工具替你定下的一套规矩,你只是没去问它按什么排。

补零方案还有个隐藏条件:位数得够。01到99补两位没事,上到100就得从000起,否则099照样压在100上头。要真稳,要么parse成整数再排,要么直接用natsort这类做自然排序的库,文件名里夹了字母数字它也能排对。

说到底你那结论我认同:机器压根没有’大小’这回事,只有你喂进去的比较规则。它永远在严格执行,问题永远是规则是不是你真正想要的。

你那脚本最后选了哪种修法?

canvas_96
[链接]

‘10’ 排在 ‘2’ 前面天经地义,这句话我盯着看了好久。
嗯…
妙的不在排序,是它冷不丁提醒你,你以为自己在做主,其实早有一套你没参与的语法,替你把世界排好了次序。字符眼里的先后,和人心里掂量的轻重,常常对不上号。仔细想想

有时觉得人和人之间也是这般。你分明把什么放在前头,对方却照另一套规矩排,怎么也拧不到一处去。补个零便好办了,可有些次序,补了零也回不去了。

classic_dog
[链接]

你这帖子让我想起以前不是这样的光景。
说实话
早些年我也犯过差不多的迷糊,不是排序,是时间。有回对两个时间戳比大小,后来的反而小,对着屏幕发了会呆——后来才晓得是时区没统一,一个当本地时间、一个当 UTC 了。机器每一步都没错,错的是我默认它懂我的意思。

有一说一你最后那句说到根子上了:它眼里的"大小",是人教给它的规则,不是人心里那套。补零也好、按数值排也好…,都是把人的逻辑翻译成它能懂的话。

现在工具越来越替人省心,反倒容易让人忘了底下那层假设。偶尔被坑一回…,也不全是坏事。我现在写东西都先想一眼它默认按啥来,习惯成自然了,btw 这坑踩过一次基本就忘不掉。

newton2006
[链接]

你那段“手写补零从没出过岔子”的经历我挺有共鸣,不过结论那句“机器眼里的顺序跟人想的不一样”,从某种角度看值得商榷。

问题不在机器“理解”错了大小,而是比较函数被默认设成了字典序(lexicographic)。字符串比较逐字符走码点,‘1’=‘1’之后比‘0’(0x30)和‘2’(0x32),0x30<0x32,于是 10 排到 2 前面——这是确定规则,不是机器有了独立意志。本质是写脚本时没显式指定按数值比,把判断权默认交给了字符串比较器。其实

补零能救急,但我自己后来被它坑过:编号超过位数上限(到 100 还只补两位)排序又乱了。后来改用 natural sort(Martin Pool 那套),把数字段当数值处理,才贴合人直觉。你当时用的什么语言、什么排序函数,有数据吗?

sudo_2000
[链接]

补零要对齐位数,否则 1、10、100 补成 1、010、100 照样乱。natural sort 更稳。

[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
需要登录后才能回复。[去登录]
回复此帖进入修真世界