如何对对象数组和数组子集进行排序

时间:2018-09-08 09:24:18

标签: javascript sorting

架构

var my_array = [ 
{
    "title": "a",
    "pinned": {
        "status": "true",
        "order": "1"
    }
},
{
    "title": "d",
    "pinned": {
        "status": "false",
        "order": "n/a"
    }
},
{
    "title": "c",
    "pinned": {
        "status": "true",
        "order": "0"
    }
},
{
    "title": "b",
    "pinned": {
        "status": "false",
        "order": "n/a"
    }
}
];

期望的行为

按字母title对对象进行排序,
除非它们的pinned状态为true
在这种情况下,将此项目的“子集”移到数组的开头,
按其pinned.order值排序。

一个示例场景是一个论坛,该论坛的帖子按日期排序,但顶部的粘性帖子按定义的顺序排序。

因此,原始架构将显示为:

[ 
{// i am at the top, because i have a pinned status of true and order of 0  
    "title": "c",
    "pinned": {
        "status": "true",
        "order": "0"
    }
},
{// i am second from the top, because i have a pinned status of true and order of 1  
    "title": "a",
    "pinned": {
        "status": "true",
        "order": "1"
    }
},
{// i follow in alphabetical order 
    "title": "b",
    "pinned": {
        "status": "false",
        "order": "n/a"
    }
},
{// i follow in alphabetical order 
    "title": "d",
    "pinned": {
        "status": "false",
        "order": "n/a"
    }
}
]

我尝试过的事情

my_array.sort(function(a, b) {
    return a.pinned.order.localeCompare(b.pinned.order) || a.title.localeCompare(b.title);
});

基于此答案:

https://stackoverflow.com/a/45741804

我也尝试过...

我考虑过根据pinned.status的值创建两个单独的数组,分别对它们进行排序,然后重新组合(如下所示),但是我想知道是否还有更优雅的方法?

var my_array = [ 
{
    "title": "a",
    "pinned": {
        "status": "true",
        "order": "1"
    }
},
{
    "title": "d",
    "pinned": {
        "status": "false",
        "order": "n/a"
    }
},
{
    "title": "c",
    "pinned": {
        "status": "true",
        "order": "0"
    }
},
{
    "title": "b",
    "pinned": {
        "status": "false",
        "order": "n/a"
    }
}
];


var my_subset = [];

for (var i = 0; i < my_array.length; i++) {

    if (my_array[i].pinned.status === "true") {
        // add to subset
        my_subset.push(my_array[i]);
        // remove from original array
        my_array.splice(i, 1);
    }

}

// sort "pruned" original array alphabetically
my_array.sort(function(a, b) {
    return a.title.localeCompare(b.title);
});

// sort subset array by pinned.order
my_subset.sort(function(a, b) {
    return a.pinned.order.localeCompare(b.pinned.order, undefined, { numeric: true });
});

// prepend subset to original array
var new_array = my_subset.concat(my_array);

// array is sorted as desired
console.log(new_array);

4 个答案:

答案 0 :(得分:2)

首先通过将数字字符串设为数字,并将布尔字符串设为布尔值来修复数据:

for (const item of my_array) {
    item.pinned.status = JSON.parse(item.pinned.status);
    item.pinned.order = Number(item.pinned.order);
}

现在,您不必将它们作为字符串进行比较。否则,您的方法基本上没问题,您只是忘记了最重要的指示符,即某项是否应该排在最前面:其pinned.status。首先进行比较,以使任何固定的项目都在没有固定的项目之前。

my_array.sort(function(a, b) {
    return -(a.pinned.status - b.pinned.status) // reverse: true before false
    || (a.pinned.status // equal to b.pinned.status
      ? a.pinned.order - b.pinned.order
      : a.title.localeCompare(b.title));
});

var my_array = [{
    "title": "a",
    "pinned": {
      "status": true,
      "order": 1
    }
  },
  {
    "title": "d",
    "pinned": {
      "status": false,
      "order": 0
    }
  },
  {
    "title": "c",
    "pinned": {
      "status": true,
      "order": 0
    }
  },
  {
    "title": "b",
    "pinned": {
      "status": false,
      "order": 0
    }
  }
];

my_array.sort(function(a, b) {
  return -(a.pinned.status - b.pinned.status) // reverse: true before false
    ||
    (a.pinned.status // equal to b.pinned.status
      ?
      a.pinned.order - b.pinned.order :
      a.title.localeCompare(b.title));
});

console.log(my_array);

您也可以

my_array.sort(function(a, b) {
    return -(a.pinned.status - b.pinned.status) // reverse: true before false
    || a.pinned.order - b.pinned.order
    || a.title.localeCompare(b.title);
});

由于未固定的项目具有相同的顺序(NaN),但前者更为明确。

答案 1 :(得分:1)

只需尝试一下:

my_array.sort(function(a, b) {
    return a.title.localeCompare(b.title);
}).sort(function(a, b) {
    return a.pinned.order.localeCompare(b.pinned.order)
});

答案 2 :(得分:0)

如果可以使用Lodash(Java实用程序库),则可以使用orderBy或sortBy:

在项目中使用Lodash:

<script src="lodash.js"></script>

使用orderBy进行排序:

_.orderBy(my_array, [function(e) { return e.pinned.status}, 'title'], ['asc', 'asc']);

more info on orderBy

答案 3 :(得分:0)

去那里:

hereIWantTheFrequencyValue

提取var my_array = [ { "title": "a", "pinned": { "status": "true", "order": "1" } }, { "title": "d", "pinned": { "status": "false", "order": "n/a" } }, { "title": "c", "pinned": { "status": "true", "order": "0" } }, { "title": "b", "pinned": { "status": "false", "order": "n/a" } } ]; var trueArr = []; var falseArr = []; var titleArr = []; var tempArr = [] for(var obj of my_array){ if(obj.pinned.status == "true"){ trueArr.push(obj); }else{ falseArr.push(obj); } } function sortArr(arr){ titleArr = []; tempArr = []; for(var obj of arr){ titleArr.push(obj.title); } titleArr = titleArr.sort(); for(var counter = 0; counter < arr.length; counter++){ tempArr.push(null); } for(var obj of arr){ tempArr[titleArr.indexOf(obj.title)] = obj; } for(counter = 0; counter < tempArr.length; counter++){ arr[counter] = tempArr[counter]; } } function addTrueFalseArr(arr){ for (var obj of arr){ my_array.push(obj) } } sortArr(trueArr); my_array = []; addTrueFalseArr(trueArr); sortArr(falseArr); addTrueFalseArr(falseArr);处的所有对象,并将它们放入数组中。然后对pinned = true所在的对象执行相同的操作。然后,根据标题对两个数组进行排序(按字母顺序),然​​后将原始数组设置为空数组-> pinned = false,然后将[]项附加到原始数组,最后附加{ {1}}个项目。