根据属性分组对javascript数组进行排序
我使用从搜索Web服务返回的json对象数组来提供jQuery.ui自动完成,在这里我使用根据对象的“族”对对象进行分组 该算法使用一个列表,其中组已经被很好地排序,这是我目前无法做到的,因此我希望在客户端组织数据。例如,如果我有以下数组:根据属性分组对javascript数组进行排序,javascript,arrays,grouping,Javascript,Arrays,Grouping,我使用从搜索Web服务返回的json对象数组来提供jQuery.ui自动完成,在这里我使用根据对象的“族”对对象进行分组 该算法使用一个列表,其中组已经被很好地排序,这是我目前无法做到的,因此我希望在客户端组织数据。例如,如果我有以下数组: var resultsArray = [ {"cat": "Category #1", "Id": "10"}, {"cat": "Category #2", "Id": "28"}, {"cat": "Category #1", "Id": "11"},
var resultsArray = [
{"cat": "Category #1", "Id": "10"},
{"cat": "Category #2", "Id": "28"},
{"cat": "Category #1", "Id": "11"},
{"cat": "Category #2", "Id": "21"},
{"cat": "Category #1", "Id": "13"}
];
我想调用resultsArray上的一个方法,以便返回
resultsArray = [
{"cat": "Category #1", "Id": "10"},
{"cat": "Category #1", "Id": "11"},
{"cat": "Category #1", "Id": "13"},
{"cat": "Category #2", "Id": "28"},
{"cat": "Category #2", "Id": "21"}
];
按cat属性分组,同时保留现有顺序
首先,我尝试对数组使用排序方法,方法是返回数组中可以找到我尝试分组依据的值的位置(假设acs.groupBy包含分组属性的名称:
items.sort(function(a, b) {
var aValue = a[acs.groupBy],
bValue = b[acs.groupBy];
var indexOfAValue = 0; // should be sthing like items.indexWhere(item[acs.groupBy] === aValue)
var indexOfBValue = 0; // same thing
return indexOfAValue - indexOfBValue;
});
with indexOfAValue将是数组中找到A的分组属性的第一个位置,但是我找不到一个简单的方法来获取和缓存这个值(数组的indexOf匹配整个对象)。你知道如何获取它吗
编辑 看起来我举了一个错误的例子:) 我不想对类别进行排序。如果类别#2发生在类别#1之前,我希望保留此信息,以便
var resultsArray = [
{"cat": "Category #3", "Id": "39"},
{"cat": "Category #2", "Id": "28"},
{"cat": "Category #1", "Id": "11"},
{"cat": "Category #2", "Id": "21"},
{"cat": "Category #1", "Id": "18"}
]
将变成(请注意,尽管我根据类别对项目进行了分组,但我没有更改类别出现的顺序,也没有根据其id更改组内的项目顺序)
这就是为什么我在上面的示例中尝试按indexOf(category)排序的原因看起来您只是在寻找一个正常的稳定排序?原生JS排序在大多数浏览器中都是稳定的(过去2年左右的所有现代浏览器),因此:
items.sort( function( a, b ){
return a.Id - b.Id;
} );
通常会工作,但并非在所有浏览器中都稳定,因此要做到这一点,请执行以下操作:
for( var i=0... ){
items[i].index = i;
}
items.sort( function( a, b ){
return ( a.Id != b.Id ) ? ( a.Id - b.Id ) : ( a.index - b.index );
}
它按Id排序,然后按原始顺序排序。您的方法正确,您的
排序功能不需要太复杂:
function group(array) {
var i, categories = {};
/* Build a map of categories and minimum indices: */
for (i = 0; i < resultsArray.length; i++) {
if (!categories[resultsArray[i].cat]) {
categories[resultsArray[i].cat] = i;
}
}
/* Sort the array using the minimum index: */
return resultsArray.sort(function(one, other) {
return categories[one.cat] - categories[other.cat];
});
}
功能组(数组){
变量i,类别={};
/*建立类别和最小索引的地图:*/
对于(i=0;i
示例:
这应该让你开始。不幸的是,该函数在数组中循环了两次(这显然不是最优的)。我强烈建议您看看下划线的一些数组功能:我将尝试了解这种稳定排序。我会尽快回来并给出结果:)这只是意味着当值相同时,它会保持原始顺序。您的方法是正确的(即保持不同项的索引),但我显然需要一种方法来跟踪列表中的原始索引(例如,通过使用哈希表)。谢谢你为我指明了正确的方向,这确实符合最初的指示。我曾尝试实施你的解决方案,但显然我没有正确理解它。从您所看到的排序没有产生正确的输出。@samy:我有一个初步的解决方案。这不是最好的,但希望它能让你开始。让我知道你的想法!我得到了同样的结果:我希望有一种方法可以一次性完成,但我找不到。您的答案是正确的:)这在某些浏览器中无法保持原始顺序
function group(array) {
var i, categories = {};
/* Build a map of categories and minimum indices: */
for (i = 0; i < resultsArray.length; i++) {
if (!categories[resultsArray[i].cat]) {
categories[resultsArray[i].cat] = i;
}
}
/* Sort the array using the minimum index: */
return resultsArray.sort(function(one, other) {
return categories[one.cat] - categories[other.cat];
});
}