PHP 的 sort 排序模式 SORT_NUMERIC/SORT_STRING/SORT_NATURAL 详解

PHP 的排序函数提供了如下几种排序模式:SORT_REGULAR - compare items normally (don’t change types)SORT_NUMERIC - compare items numericallySORT_STRING - compare items as stringsSORT_LOCALE_STRING - compare items as strings, based on the current locale. It uses the locale, which can be changed using setlocale()SORT_NATURAL - compare items as strings using “natural ordering” like natsort()SORT_FLAG_CASE - can be combined (bitwise OR) with SORT_STRING or SORT_NATURAL to sort strings case-insensitivelySORT_REGULARSORT_REGULAR,默认排序模式,会依照数组成员的原数据类型进行排序:字符串类型使用 ASCII 码字符串排序,即按位依次比较 ASCII 码大小,如相同则比较下一位,比如 “2” > “12"数值类型使用数值排序,即 2 < 12虽然 PHP 的数组高度灵活,可以存储不同类型值,但如果参与排序,建议格式统一类型。否则数据会被划分成两块:字符串类型区/数值类型区。然后分别按各自的默认规则进行排序:<?php$arr = [12, 2, 31, 302, “c”, “a2”, “a12”, 1];sort($arr);print_r($arr);// 字符串按ASCII排序 a12 < a2 < c / 数值按自然排序Array( [0] => a12 [1] => a2 [2] => c ———– [3] => 1 [4] => 2 [5] => 12 [6] => 31 [7] => 302)可以看到,字符串类型(ASCII排序)和数值类型(数值排序)的元素被分开使用各自的默认规则排序,也可以说默认排序以:字符串<数值作为升序。SORT_STRING & SORT_LOCALE_STRINGSORT_STRING 会尝试将元素都当做字符串数据进行排序处理,而且这种模式是安全的,因为数值类型转字符串类型不会有什么非法或截断的问题,然后按照 ASCII排序 进行处理。<?php$arr = [12, 2, 31, 302, “c”, “a2”, “a12”, 1];sort($arr, SORT_STRING);print_r($arr);//可以看到元素以ASCII位序进行排列 比如 “12” < “2” “302” < “31"Array( [0] => 1 [1] => 12 [2] => 2 [3] => 302 [4] => 31 [5] => a12 [6] => a2 [7] => c)SORT_NUMERICSORT_NUMERIC会将元素当做数值类型处理,在使用时需要注意元素的类型,比如示例中的 “a2”, “a12”, “c” 元素并不能安全的由字符串类型转为数值类型,所以排序会将他们放置在最前并不参与排序(原样奉还),“1"可以转为 1,则可以参与排序。<?php$arr = [12, 2, 31, 302, “c”, “a2”, “1”, “a12”];sort($arr, SORT_NUMERIC);print_r($arr);//无法转为数值类型的元素不会参与排序 会保持原先后顺序返回Array( [0] => c [1] => a2 [2] => a12 ———- [3] => 1 [4] => 2 [5] => 12 [6] => 31 [7] => 302)SORT_NATURALSORT_NATURAL看字面意思理解就是自然排序,特点在于对字符串+数值类型的数据也能以对人类友好的方式排序出来。比如待排序数列:“a2” “a12” “c1” “c12"对我们来说,最为容易理解的是先按照字母排序,字母相同的时就按后面的数值整体做排序,即: a2 < a12 < c1 < c12 这个样子先看一下默认的和其他几种排序模式会得到什么结果:SORT_REGULAR:会以 ASCII 字符串排序的方式处理数据 a12 < a2 < c12 < c2 不太自然SORT_STRING:同SORT_REGULAR,a12 < a2 < c12 < c2 不太自然SORT_NUMERIC:数据无法转为数值,无法做排序处理如果使用 SORT_NATURAL 模式呢?SORT_NATURAL便可以按照我们最容易理解的方式对数据进行排序:SORT_NATURAL 模式:a2 < a12 < c2 < c12,可以看到SORT_NUMERIC结合了SORT_STRING+SORT_NUMERIC处理机制大概如下:1、元素可以转为数值, 则做数值自然排序2、元素无法转为数值, 则对元素非数值部分做字符串排序,如果有数值部分则对数值部分做数值排序3、以数值<字符串的升序对数据做分区排列。<?php$arr = [12, 2, 31, 302, “c12”, “a2”, “1”, “a12”, “c1”];sort($arr, SORT_NATURAL);print_r($arr);// “1” 被转为了 1 进行排序// “c12”, “a2”, “a12”, “c1” 以对我们理解友好的方式排序Array( [0] => 1 [1] => 2 [2] => 12 [3] => 31 [4] => 302 ———— [5] => a2 [6] => a12 [7] => c1 [8] => c12)自然排序还有个有个函数natsort可以做保留索引的自然排序,类似 asort($arr, SORT_NATURAL)SORT_FLAG_CASESORT_FLAG_CASE主要配合 SORT_STRING 和 SORT_NATURAL对字符处理时是否忽略大小写,这个很容易理解。 ...

March 13, 2019 · 2 min · jiezi

JavaScript sort() 排序的坑详解

前言:做项目的时候发现使用sort排序后的代码,在android和ios平台解析的结果不一样。1、先从简单的开始,大家都知道sort()函数比较的是ASCII码的大小,而且而且而且:Array的sort()方法默认把所有元素先转换为String再排序,所以就有以下问题。// baiDu排在了最后:[‘Google’, ‘baiDu’, ‘Facebook’].sort(); // [‘Facebook’, ‘Google", ‘baiDu’]// 无法理解的结果:[10, 20, 1, 2].sort(); // [1, 10, 2, 20]结果转换成字符串比较,‘10’排在了'2’的前面,因为字符'1’比字符'2’的ASCII码小2、使用回调函数的错误[10, 2, 3, 100, 6, 9].sort((a, b) => { return a < b;});// 无法理解的结果[10, 2, 3, 100, 6, 9]排序前后结果没有变化问题分析:在sort实现的规范中有这么一条 sortFun(a,b) === 0,则有 a === b 且 b === a 。此时我们再看var sortFun = (a, b) => a < b,它等同于var sortFun = (a, b) => a < b ? 1 : 0。它有一个隐藏的漏洞:当a >= b时,sortFun(a,b) === 0。而根据规范,通过sortFun(a,b) === 0可以推测出a === b,显然这里互相矛盾, 反之亦然(a > b的情况)。所以比较的时候最好使用 a - b 或者 b - a正确写法:[10, 2, 3, 100, 6, 9].sort((a, b) => { return a - b;});// 结果[2, 3, 6, 9, 10, 100]android 和 ios平台解析的sort函数实现方式不同,不规范的写法可能导致解析结果不同 ...

January 31, 2019 · 1 min · jiezi