Javascript 迭代法实现数组多条件排序
多条件排序可能有很多种思路,效率也各不相同,我的方法可能只适合自己用,毕竟目的是为了实现功能,所以采用了最笨的方法,不过效果还是很理想的,经过多次测试,6列1000行数据,平均排序时间大约是:28ms。
具体实现代码如下:
function isArr(data) {
return ({}).toString.call(data) == '[object Array]';
}
function getIndex(arr) {
var i = 0,
len = arr.length
keys = [];
while (i < len) {
keys.push(i++);
}
return keys;
}
// 检测数组最大维数,非数组则返回-1,如果有num则表明检测数组是否为指定维数
function checkArrDim(arr, num) {
var dimension = -1,
num = parseInt(num),
isCheck = isNaN(num) ? false : true,
dm = [0], i, len, mx;
if (isArr(arr) && (len = arr.length) > 0) {
dimension = 1; // 任何一个数组,只要有数据,至少是个1维
for (i = 0; i < len; i++) {
dm.push(checkArrDim(arr[i])); // 递归获取每个元素的维数,如果dm数组中全是-1则说明arr是1维数组
}
dimension = (mx = Math.max.apply(null, dm)) === -1 ? dimension : dimension + mx;
}
// 如果dm数组长度 <= 1则说明arr压根不是数组,或者是空数组
// 当dm数组长度 > 1,且dimension == 1,说明arr是1维数组
// 或者dimension <> 1,因为dm默认填充1个0,只要所有元素的和 / dm去掉0后的长度 == num - 1,即说明是n维数组
return isCheck ? (dm.length > 1 ? (dimension == 1 && num == 1) || eval(dm.join('+')) / (dm.length - 1) == num - 1 : false) : dimension;
}
function msort(arr, field, order) {
if (!checkArrDim(arr, 2) || !checkArrDim(field, 1) || !checkArrDim(order, 1)) {
return ;
}
var key, tmp, val, sa, sk, pre;
var i, ilen, j, jlen, k, klen, m, mlen;
var range = [], rng;
// 按已排序数组的索引数组排序待定数组
var sortFromKey = function (data, key) {
var tmp = [], i, j, len;
for (i = 0, len = key.length; i < len; i++) {
tmp.push(data[key[i]]);
}
for (j = 0; j < len; j++) {
data[j] = tmp[j];
}
};
// 多条件排序
for (i = 0, ilen = field.length; i < ilen; i++) {
tmp = arr[field[i]];
if (i === 0) {
// 第1次排序,直接对当前字段所在数组排序
key = getIndex(tmp);
tmp.mergeSort(key, order[i]);
range.push([0, tmp.length - 1]);
} else {
// 如果有第2个及以上的条件,则均以前1个条件为参照,获取前1个已排序数组
// 内每一组相同元素的区间,对该区间内元素赋值到临时数组并排序,并获取排序
// 索引,最终拼接在一起这个拼接在一起的新的索引数组即是其它所有数组排序的参照,
// 经过上述循环执行,即可完成多条件排序
// ↓核心工作前的初始工作
pre = arr[field[i - 1]]; // 前1个已排序数组
val = pre[0];
sa = [tmp[0]];
sk = [0];
key = [];
rng = [];
// 本排序核心工作即整理已排序数组的同值区间,此区间是当前待排序数组多个排序区间的唯一参照
for (k = 0, klen = range.length; k < klen; k++) {
for (m = range[k][0] + 1, mlen = range[k][1] + 1; m <= mlen; m++) { // 注意此处条件表达式,需要额外执行一次排序和初始化
if (val === pre[m] && m !== mlen) { // 无论区间多小,哪怕只有1个元素,当m = mlen时必须执行排序和下一步的初始准备
sa.push(tmp[m]);
sk.push(m);
} else {
rng = rng.concat([[sk[0], sk[sk.length - 1]]]);
sa.mergeSort(sk, order[i]); // 主要是为了获取sk
key = key.concat(sk);
val = pre[m];
sa = [tmp[m]];
sk = [m];
}
}
}
range = rng; // 获取整理后的待排序区间
sortFromKey(tmp, key); // 对当前数组排序
}
// 经过前面的过程,一个条件已经排序完成,并且获得排序后的原索引(数组)
// 然后对除了当前字段数组外的其它所有数组按已排序索引重新排列
for (j = 0, jlen = arr.length; j < jlen; j++) {
if (j == field[i]) {
continue;
}
sortFromKey(arr[j], key);
}
}
}
其中用到数组mergeSort()是自己定义到Array.prototype的方法,链接地址:Javascript-归并排序
Javascript 迭代法实现数组多条件排序的更多相关文章
- js 数组sort, 多条件排序。
Array.sort(); sort()方法可以传入一个函数作为参数,然后依据该函数的逻辑,进行数组的排序. 一般用法:(数组元素从小大进行排序) var a = [9, 6, 5, 7, 11, 5 ...
- javascript:算法之数组sort排序
数组sort排序 sort比较次数,sort用法,sort常用 描述 方法sort()将在原数组上对数组元素进行排序,即排序时不创建新的数组副本.如果调用方法sort()时没有使用参数,将按字母顺序( ...
- JavaScript中对数组的排序
将下列对象数组,通过工资属性,由高到低排序 var BaiduUsers = [], WechatUsers = []; var User = function(id, name, phone, ge ...
- javascript中关于数组的一些鄙视题
一.判断一个数组中是否有相同的元素 /* * 判断数组中是否有相同的元素的代码 */ // 方案一 function isRepeat1(arrs) { if(arrs.length > 0) ...
- JavaScript中的数组详解
JavaScript中的数组 一.数组的定义 数组是值的有序集合,或者说数组都是数据的有序列表. 二.创建数组 [字面量形式] 1.空数组 var arr=[]; 2.带有元素的数组 var arr= ...
- javascript中的数组操作
1.数组的创建 var arrayObj = new Array(); //创建一个数组 var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上限, ...
- JavaScript高级特性-数组
1. JavaScript中的数组 在C++.Java中,数组是一种高效的数据结构,随机访问性能特别好,但是局限性也特别明显,就是数组中存放的数据必须是同一类型的,而在JavaScript中,数组中的 ...
- JavaScript中Array(数组) 对象
JavaScript中Array 对象 JavaScript中创建数组有两种方式 (一)使用直接量表示法: var arr4 = []; //创建一个空数组var arr5 = [20]; // 创建 ...
- JavaScript中操作数组的方法
JavaScript Array 对象 对数组操作的方法分为两种 一种是会改变原始数组的变异方法,还有一种是不会改变原始数组的非变异方法. 总结 巧记 Push() 尾部添加 pop() 尾部删除 U ...
随机推荐
- plsql的参数IN和OUT
代码片段一 create or replace procedure scott.pro_para_inout(p_dname in out scott.dept.dname%TYPE, p_loc o ...
- cloudstack安装篇2-主机名配置
CloudStack要求正确配置主机名.在默认情况下,安装完操作系统后,主机名是localhost.localdomain.运行下面的命令来测试: hostname --fqdn 在此处将返回这样的结 ...
- linux内核系列(一)编译安装Linux内核 2.6.18
1.配置环境 操作系统:CentOS 5.2 下载linux-2.6.18版本的内核,网址:http://www.kernel.org 说明:该编译文档适合2.6.18以上的Linux内核版本,只需所 ...
- POJ2752 - Seek the Name, Seek the Fame(KMP)
题目大意 给定一个字符串S,求出所有既是S的前缀又是S的后缀的子串长度 题解 从末尾位置倒推,经过的失配函数值就是题目要求求的 代码: #include <iostream> #inclu ...
- Robocopy是微软Windows Server 2003资源工具包中众多多用途的实用程序之一(它是基于强大的拷贝程序
Robocopy是微软Windows Server 2003资源工具包中众多多用途的实用程序之一(它是基于强大的拷贝程序).没错,Robocopy的功能是拷贝文件,你也许会觉得无聊并且要翻阅下一篇文章 ...
- arm 交叉编译时 gcc 的 Options
https://sourceware.org/binutils/docs/as/ARM-Options.html https://gcc.gnu.org/onlinedocs/gcc-4.5.3/gc ...
- mysql 中文乱码的解决办法
I would not suggest Richies answer, because you are screwing up the data inside the database. You wo ...
- ssh -CT -o BatchMode=yes 用户名@主机名
- Centos环境下Tomcat启动缓慢
最近项目上线部署的时候,发现一个问题.Tomcat在启动过程中耗费了很长的时间.查看日志,发现耗时最长的地方是:INFO [localhost-startStop-1] org.apache.cata ...
- "判断this指针是不是null有什么意义呢"
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:"判断this指针是不是null有什么意义呢".