-
2021-03-24 12:00:22
简介:PHP 5.3+的一个非常通用的解决方案
我想在这里添加我自己的解决方案,因为它提供了其他答案没有的特性。
具体而言,该解决方案的优点包括:它是
可重复使用:将排序列指定为变量,而不是硬编码。
它是
柔韧:您可以指定多个排序列(任意数量)-其他列用作初始比较相等的项之间的连接符。
它是
可逆:您可以指定对每一列分别进行倒排。
它是
可扩展*如果数据集包含不能以“哑”方式(例如日期字符串)比较的列,则还可以指定如何将这些项转换为可直接比较的值(例如
DateTime)。
它是
如果你愿意的话:此代码负责项的排序,但是
你,你们选择实际的排序函数(
usort或
uasort).
最后,它不使用
array_multisort*同时
array_multisort很方便,它依赖于在排序之前创建所有输入数据的投影。这会消耗时间和内存,如果您的数据集很大,这可能会使人望而却步。
密码function make_comparer() {
// Normalize criteria up front so that the comparer finds everything tidy
$criteria = func_get_args();
foreach ($criteria as $index => $criterion) {
$criteria[$index] = is_array($criterion)
? array_pad($criterion, 3, null)
: array($criterion, SORT_ASC, null);
}
return function($first, $second) use (&$criteria) {
foreach ($criteria as $criterion) {
// How will we compare this round?
list($column, $sortOrder, $projection) = $criterion;
$sortOrder = $sortOrder === SORT_DESC ? -1 : 1;
// If a projection was defined project the values now
if ($projection) {
$lhs = call_user_func($projection, $first[$column]);
$rhs = call_user_func($projection, $second[$column]);
}
else {
$lhs = $first[$column];
$rhs = $second[$column];
}
// Do the actual comparison; do not return if equal
if ($lhs
return -1 * $sortOrder;
}
else if ($lhs > $rhs) {
return 1 * $sortOrder;
}
}
return 0; // tiebreakers exhausted, so $first == $second
};}
如何使用
在本节中,我将提供对此示例数据集进行排序的链接:$data = array(
array('zz', 'name' => 'Jack', 'number' => 22, 'birthday' => '12/03/1980'),
array('xx', 'name' => 'Adam', 'number' => 16, 'birthday' => '01/12/1979'),
array('aa', 'name' => 'Paul', 'number' => 16, 'birthday' => '03/11/1987'),
array('cc', 'name' => 'Helen', 'number' => 44, 'birthday' => '24/06/1967'),);
基本
功能make_comparer接受定义所需排序的变量数,并返回一个函数,您应该使用该函数作为参数usort或uasort.
最简单的用例是传递您希望用来比较数据项的键。$data被name你会做的事usort($data, make_comparer('name'));
如果项是数字索引数组,则键也可以是数字。对于问题中的例子,这将是usort($data, make_comparer(0)); // 0 = first numerically indexed column
多排序列
可以通过将附加参数传递给make_comparer。例如,按“Number”排序,然后按零索引列排序:usort($data, make_comparer('number', 0));
高级特征
如果将排序列指定为数组而不是简单的字符串,则可以使用更高级的功能。这个数组应该进行数字索引,并且必须包含以下项:0 => the column name to sort on (mandatory)1 => either SORT_ASC or SORT_DESC (optional)2 => a projection function (optional)
让我们看看如何使用这些特性。
反向排序
按名称降序排序:usort($data, make_comparer(['name', SORT_DESC]));
按数字降序排序,然后按名称降序排序:usort($data, make_comparer(['number', SORT_DESC], ['name', SORT_DESC]));
自定义投影
在某些情况下,您可能需要按值不能很好地进行排序的列进行排序。示例数据集中的“生日”列符合以下描述:将生日作为字符串进行比较是没有意义的(例如,“01/01/1980”在“10/10/1970”之前)。在这种情况下,我们希望指定如何工程项目表单中的实际数据能,会,可以直接与所需的语义进行比较。
投影可以指定为任何类型的可赎回*字符串、数组或匿名函数。假设投影接受一个参数并返回其投影形式。
应该注意的是,虽然预测类似于自定义比较函数,但是usort而且,它们更简单(只需将一个值转换为另一个值),并利用所有已经分解成的功能。make_comparer.
让我们对没有投影的示例数据集进行排序,看看会发生什么:usort($data, make_comparer('birthday'));
这不是期望的结果。但我们可以用date_create作为预测:usort($data, make_comparer(['birthday', SORT_ASC, 'date_create']));
这是我们想要的正确命令。
预测还有更多的事情可以实现。例如,获取不区分大小写的排序的快速方法是使用strtolower作为投影。
尽管如此,我还应该提到,如果数据集很大,最好不要使用投影:在这种情况下,在不使用投影的情况下手动投影所有数据,然后进行排序将会更快,尽管这样做会使内存使用量增加,以换取更快的排序速度。
最后,下面是一个使用所有功能的示例:它首先按数字降序排序,然后按生日升序排序:usort($data, make_comparer(
['number', SORT_DESC],
['birthday', SORT_ASC, 'date_create']));
更多相关内容 -
关于C语言多维数组和VB语言多维数组的实际数据在内存中的储存排列方式
2018-03-02 14:38:56C语言多维数组的申明:long cArr[3][10];VB语言的多维数组的申明:dim vbArr...那么C语言的多维数组和VB语言的多维数组在内存中的存储方式到底是什么样的呢?两个一样还是不一样呢?下面我们来通过实验来验证它们的...C语言多维数组的申明:long cArr[3][10];
VB语言的多维数组的申明:dim vbArr(2,9) as long,这里假设Option Base 0,这里只说数组数据的实际存储,不考虑SafeArr结构,关于vb数组的SafeArr结构测试在另外一篇文章中。
那么C语言的多维数组和VB语言的多维数组在内存中的存储方式到底是什么样的呢?两个一样还是不一样呢?下面我们来通过实验来验证它们的存储排列方式。
一、对于一维数组,两种语言在内存中的存储排列方式是一样的,都是按行顺序存储排列的,即:
C语言:cArr[0][0]->cArr[0][9]->cArr[1][0]->cArr[1][9]->cArr[2][0]->cArr[2][9]
VB语言:vbArr(0,0)->vbArr(0,9)->vbArr(1,0)->->vbArr(1,9)->->vbArr(2,0)->->vbArr(2,9)
二、对于多维数组,这两种语言的存储排列方式就有了差别,C语言是按行顺序排列的,VB语言是按列顺序存储排列的,下面使用二维数组的一个实验来证明这一点。
C语言源码:
int main()
{
long cArr[3][10];
int r;
int i,j;
int n;
n=0;
printf("i=0 ");
for(i=0;i<3;i++)
for(j=0;j<10;j++){
cArr[i][j]=(i*10+j);
if (n!=i){
printf("\n");
n=i;
printf("i=%d ",i);
}
printf("%d ",cArr[i][j]);
}
printf("\n-----------------------------------------------------------------------------\n");
n=0;
printf("i=0 ");
for(i=0;i<3;i++)
for(j=0;j<10;j++){
if (n!=i){
printf("\n");
n=i;
printf("i=%d ",i);
}
printf("%p ",&cArr[i][j]);
}
}运行结果:
i=0 0 1 2 3 4 5 6 7 8 9
i=1 10 11 12 13 14 15 16 17 18 19
i=2 20 21 22 23 24 25 26 27 28 29
-----------------------------------------------------------------------
i=0 0028FEC0 0028FEC4 0028FEC8 0028FECC 0028FED0 0028FED4 0028FED8 0028FEDC 0028FEE0 0028FEE4
i=1 0028FEE8 0028FEEC 0028FEF0 0028FEF4 0028FEF8 0028FEFC 0028FF00 0028FF04 0028FF08 0028FF0Ci=2 0028FF10 0028FF14 0028FF18 0028FF1C 0028FF20 0028FF24 0028FF28 0028FF2C 0028FF30 0028FF34
从源码和运行结果大家可以看到,使用cArr[0][0]这样下标的方式取得到数据,先是cArr[0][0]->cArr[0][9],然后是cArr[1][0]->cArr[1][9],再后来是cArr[2][0]->cArr[2][9],数据是连续存放的,那么它们的存储地址是多少呢?看横线的下面,cArr[0][0]的内存地址从0028FEC0开始,每一个数据都比上一个数据的存储地址都增加了4个字节,证明一维是连续存放的;现在看cArr[0][9]到cArr[1][0]也是连续的,从地址0028FEE4到 0028FEE8,看cArr[1][9]到cArr[2][0]也是连续的,从地址0028FF0C到 0028FF10,通过以上实验可以看出C语言的多维数组在内存中数据存储方式是按行连续存放的。下面看Vb的多维数组存储方式会不会一样呢?
VB源代码:
Private Sub Command1_Click()
Dim VbArr(2, 9) As Long
Dim i As Integer, j As Integer
Dim p As Long
Debug.Print "输出值:"
For i = 0 To UBound(VbArr, 1)
Debug.Print i,
For j = 0 To UBound(VbArr, 2)
VbArr(i, j) = i * 10 + j
Debug.Print Format(VbArr(i, j), " 00 ");
Next
Debug.Print
Next
Debug.Print "---------------------------------------------------------------------------------------------------------------------------------"
Debug.Print "输出地址"
For i = 0 To UBound(VbArr, 1)
Debug.Print i,
For j = 0 To UBound(VbArr, 2)
p = VarPtr(VbArr(i, j))
Debug.Print Format(p, "00000000 ");
Next
Debug.Print
Next
End SubVB语言的输出结果如下:
输出值:
0 00 01 02 03 04 05 06 07 08 09
1 10 11 12 13 14 15 16 17 18 19
2 20 21 22 23 24 25 26 27 28 29
---------------------------------------------------------------------------------------------------------------------------------
输出地址
0 129810376 129810388 129810400 129810412 129810424 129810436 129810448 129810460 129810472 129810484
1 129810380 129810392 129810404 129810416 129810428 129810440 129810452 129810464 129810476 129810488
2 129810384 129810396 129810408 129810420 129810432 129810444 129810456 129810468 129810480 129810492(1) VbArr(0,0)的存储地址是129810376,VbArr(0,1)的存储地址是129810388,这两个差12个字节,因为数组是长整型数组,每个元素占4个字节,所以说这两个地址不是连续地址,以此类推,按行排列的地址,相邻两地址都差12个字节,正好是三个元素占用的地址,即每列的行数*每个元素占用字节数,正好是12个字节。
(2) VbArr(0,0)的存储地址是129810376,VbArr(1,0)的存储地址是129810380,这两个差4个字节,因为数组是长整型数组,每个元素占4个字节,所以说这两个地址是连续地址,是列相连。(3) VbArr(2,0)的存储地址是129810384,VbArr(0,1)的存储地址是129810388,这两个差4个字节,因为数组是长整型数组,每个元素占4个字节,所以说这两个地址是连续地址。
(4) 通过对vb字符串多维数组进行分析,数据也是按列的顺序存放的.
以此类推,可以推算出,VB多维数组是按列排列存储,是一列一列的连续存放的。
-
C++中 关于多维数组在计算机内存中的分配情况
2013-04-02 14:35:59在C++ 中,数组在内存的分配情况如何呢?我们可以编写如下程序,可以读取到一个二维数组的每一个元素在内存中的地址,为了更清楚的了解,我在这里采用了两种遍历方式: #include "stdafx.h" #include using ...
在C++ 中,数组在内存的分配情况如何呢?我们可以编写如下程序,可以读取到一个二维数组的每一个元素在内存中的地址,为了更清楚的了解,我在这里采用了两种遍历方式:
#include "stdafx.h" #include <iostream> using namespace std; /* 查看数组的内存分配 */ void Array_Memory_Allocate() { int Arr[3][4]; for(int i = 0 ; i < 3 ; i++) { for(int j = 0 ; j < 4 ; j++) { cout << "Arr[" << i << "][" << j << "]: " << &Arr[i][j] << endl; } } cout << "\n\n" ; for(int j = 0 ; j < 4 ; j++) { for(int i = 0 ; i < 3 ; i++) { cout << "Arr[" << i << "][" << j << "]: " << &Arr[i][j] << endl; } } } int _tmain(int argc, _TCHAR* argv[]) { Array_Memory_Allocate(); return 0; }
C++中,二维数组中元素排列的顺序是:按行存放,即在内存中先顺序存放第一行的元素,再存放第二行的元素。下图表示对a[3][4]数组存放的顺序。
C++允许使用多维数组。有了二维数组的基础,再掌握多维数组是不困难的。例如,定义三维数组的方法是:
float a[2][3][4];
定义float型三维数组a,它有2×3×4=24个元素。多维数组元素在内存中的排列顺序:第一维的下标变化最慢,最右边的下标变化最快。例如,上述三维数组的元素排列顺序为:
a[0][0][0]→a[0][0][1]→a[0][0][2]→a[0][0][3]→a[0][1][0]→a[0][1][1]→a[0][1][2]→a[0][1][3]→a[0][2][0]→a[0][2][1]→a[0][2][2]→a[0][2][3]→a[1][0][0]→a[1][0][1]→a[1][0][2]→a[1][0][3]→a[1][1][0]→a[1][1][1]→a[1][1][2]→a[1][1][3]→a[1][2][0]→a[1][2][1]→a[1][2][2]→a[1][2][3] -
C++ 多维数组 分配连续内存空间
2021-10-25 17:24:183维数组举例 int*** malloc_arr(int x, int y, int z, int default_value = 0) { // 分配空间 int*** arr = new int** [x]; arr[0] = new int* [x * y](); arr[0][0] = new int[x * y * z](); // 初始化第二维...3维数组举例
int*** malloc_arr(int x, int y, int z, int default_value = 0) { // 分配空间 int*** arr = new int** [x]; arr[0] = new int* [x * y](); arr[0][0] = new int[x * y * z](); // 初始化第二维 for (int i = 1; i < x; i++) arr[i] = arr[i - 1] + y; // 初始化第三维 int** p = arr[0]; for (int i = 1; i < x * y; i++) p[i] = p[i - 1] + z; // 设置初始置 if (default_value != 0) { int* pp = &arr[0][0][0]; for (int i = 0; i < x * y * z; i++) *pp++ = default_value; } return arr; } void free_arr(int*** & arr) { if (arr) { delete arr[0][0]; delete arr[0]; delete arr; } arr = nullptr; }
void test_use() { int*** arr = malloc_arr(2, 3, 4, 666); printf("%d\n", arr[0][0][0]); printf("%d\n", arr[1][0][0]); printf("%d\n", arr[0][1][0]); printf("%d\n", arr[0][0][1]); printf("%d\n", arr[1][2][3]); free_arr(arr); }
比起多个for的嵌套new来分配,这种分配方式显然更合理,连续内存块对指针也更友好
对于分配 x ∗ y ∗ z x * y * z x∗y∗z 的空间,总共需要 x 3 + y 2 + z x^3 + y^2 + z x3+y2+z 的内存
-
[JAVA] 数组、多维数组,动态、静态初始化,数组JVM内存模型分析
2021-03-22 17:46:34Java 数组、多维数组,动态、静态初始化,数组JVM内存模型分析什么是数组所谓数组,是具有相同数据类型的若干变量或者数据按照一定排序规则组合起来的一种数据存储格式。数组中的数据称为数组元素,我们使用索引来... -
一维数组与多维数组
2022-03-07 09:58:45数组的理解:数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名, * 并通过编号的方式对这些数据进行统一管理。 * * 2.数组相关的概念: * >数组名 * >元素 * >角标、下标、索引 *... -
Cherno C++系列笔记22——P64~P65 多维数组、std::sort排序
2022-04-07 14:26:27尽量使用一维数组代替多维数组提高内存访问效率1.4.1.缓存命中和缓存不命中1.4.2.用一维数组代替二维数组 1.P64 多维数组 参考:视频 笔记 1.1.二维数组的内存分配和初始化 1.1.1.内存分配 多维数组实际上就是数组的... -
vector 容器(02)—— vector表示的多维数组
2019-02-21 20:26:021、vector中嵌套一个vector容器,来表示一个二维数组 #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; void Test01() { vector<... -
c语言 多维数组.doc
2021-05-22 18:33:37c语言 多维数组c语言 多维数组一、高维数组有时,数组的维数并不止一维,例如一个记录消费中心在第一季度里各个月的收入数据就可以用二维数组来表示。定义二维数组的方法是在一维数组定义的后面再加上一个用方括号括... -
js多个(N)个数组的的元素组合排序算法,多维数组的排列组合或多个数组之间的排列组合
2021-03-14 18:11:00内存大小有[‘16G‘,‘32G‘,‘64G‘,‘128G‘],版本有[‘移动‘,‘联通‘,‘电信‘],要求写一个算法,实现[[‘白色‘,‘16G‘,‘移动‘], [‘白色‘,‘16G‘,‘联通‘] ...]这样的组合,扩张,如果后面... -
数组以及多维数组
2021-07-14 15:11:52首先必须声明数组变量,才能在程序中使用数组。 语法: dataType[] arrayRefVer;//首选 或者: dataType arrarrefver[] Java语言中使用new操作符来创建数组, 语法: dataType[] arrayRefVer -
C++多维数组:存储方式、访问方式和作为函数参数
2017-02-07 17:53:58C++中数组可以嵌套,就是多维数组。 多维数组存储与访问方式 二维数组:一维数组可对应数学中的向量,而二维数组可对应矩阵,可用一个二维数组存储矩阵。 图1 二维数组mat示意图 二维数组的横向称为行,... -
js用递归遍历多维数组_三分钟带你了解js基础语法
2020-11-21 23:05:04JS 基础语法(重点总结)变量变量即一个带名字的用来存储数据的内存空间,数据可以存储到变量中,也可以从变量中取出数变量的声明以及注意点:JavaScript 是一种弱类型语言,在声明变量时不需要指明数据类型,直接用 ... -
[JAVA]Java 数组、多维数组,动态、静态初始化,数组JVM内存模型分析
2020-03-22 17:54:02[#### 数组、多维数组,静态、动态初始化,都说明白了] 什么是数组 所谓数组,是具有相同数据类型的若干变量或者数据按照一定排序规则组合起来的一种数据存储格式。数组中的数据称为数组元素,我们使用索引来标识... -
C语言的简单使用(十二、多维数组)
2019-09-12 15:49:57多维数组是指二维往上,包括二维的数组,这些知识在编程的过程中几乎用不到,但是它能更好地帮助程序员理解变量在内存中的分布。 -
二维数组和多维数组的本质及寻址方式
2020-12-23 21:45:09二维数组和多维数组的本质及寻址方式 二维数组和多维数组的本质还是一维数组,一维数组是一个特殊的一维数组。数组的数组就是多维数组,这个数组的元素不是基本数据类型,而是数组。 ... -
[JAVA] Java 数组、多维数组,动态、静态初始化,数组JVM内存模型分析
2021-03-08 08:29:26数组中的数据称为数组元素,我们使用索引来标识数组元素在数组中的存储位置,索引从0开始,步长是1,其后的索引依次递增:其中,数据类型包括以下两种:基本数据类:byte,short,int,long,float,double,char,... -
Java 数组、多维数组,动态、静态初始化,数组JVM内存模型分析
2021-03-09 19:06:07Java 数组、多维数组,动态、静态初始化,数组JVM内存模型分析什么是数组所谓数组,是具有相同数据类型的若干变量或者数据按照一定排序规则组合起来的一种数据存储格式。数组中的数据称为数组元素,我们使用索引来... -
数据结构复习之多维数组与矩阵
2021-07-11 08:55:58多维数组与矩阵知识点多维数组和运算定义顺序存储二维存储位置计算三维数组存储位置数组转换置算法实现矩阵的压缩存储对称矩阵三角矩阵稀疏矩阵三元组表来存储稀疏实例一般㔹置算法快速转置算示带行表的三元组表 ... -
数组、二维数组、多维数组、交错数组
2019-07-10 15:07:26把具有相同类型的若干元素按无序的形式组织起来,这些无序排列的同类型元素的集合被称为数组。 二、数组的基本结构 1.基本申明形式 基本结构:变量类型[]变量名 = new 变量类型[数组长度]{元素,元素,元素}; ... -
c语言 一维数组 多维数组的理解
2021-05-19 05:28:18数组在程序设计中,为了处理方便,把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。在C语言中,数组属于构造数据类型。一个数组可以分解为多个数组元素,这些数组元素... -
详解多维数组与指针之间的关系
2018-04-16 18:22:43在内存中示意图是:在CPU看来内存是一组连续的地址空间,所以当我们对一维数组进行操作时只需要知道数组首地址,就可以通过地址偏移加减运算方式来求得每个元素位于内存中的文件映射出来的数据段虚拟地址!... -
科学网—Python: NumPy中的多维数组ndarray - 刘洋洋的博文
2020-11-21 01:48:361 Python中的数组- 用list和tuple等数据结构表示数组- 一维数组 List1 = [1, 2, 3]- 二维数组 Tuple1 = ([1, 2, 3], [4, 5, 6], [7, 8, 9])但是:列表是动态指针数组,它保存的是对象的指针,其元素可以是任意类型的... -
数组介绍与多维数组
2021-05-31 11:56:14目录一、什么是数组?二、数组的声明和创建三、初始化和内存分析(一)三...必须首先声明数组变量,才能在程序中使用数组。 int[] nums;//首选方法 int nums[]; java语言中使用new关键字来创建数组 int[] nums = n -
VB6之多维数组中元素在内存中的排列情况
2014-07-12 16:50:00数组元素在内存中的排列情况: 13 ' a[0]|a[1]|a[2] 14 15 Debug.Print " 二维数组: " 16 Debug.Print VarPtr(b( 0 , 0 )), VarPtr(b( 1 , 0 )), VarPtr(b( 2 , 0 )) 17 Debug.Print VarPtr(b( ... -
一维数组、二维(多维)数组,数组初始化、获取数组指定位置元素、获取数组长度、遍历数组、数组的内存结构
2021-12-22 16:23:41概括 数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。 -
多维数组和广义表(C++)
2018-04-21 22:16:23对于多维数组和广义表是一种复杂的非线性结构,它们的逻辑特征是:一个元素可能有多个直接前趋和多个直接后继。 一、数组概念 一维数组 可以看成是一个线性表或一个向量,在计算机中是一段连续的存储单元,适用... -
关于数组在内存中的存放
2015-09-04 20:49:16由腾讯的一个笔试题牵涉的知识点,自己之前没有接触过,就总结了一下: ...【解析】若在内存中,则数据可以”随机存取”,但内存数据被读取或写入时,所需要的时间与这段信息所在的位置无关.但是在读 -
Nmupy的灵魂:ndarray多维数组对象
2021-12-08 10:45:48前言 ndarray是一个n维数组对象,是Python中一个快速灵活的大型数据集容器,允许我们使用类似于标量的操作语法在整块数据上进行计算。...numpy主要用于多维数组和矩阵运算,在numpy中的多维数组和矩阵就是ndarray对象,