按两个值排序,其中一个值具有优先级

83

如何按升序排序此数据的 countyear 值,优先考虑 count 值?

//sort this
var data = [
    { count: '12', year: '1956' },
    { count: '1', year: '1971' },
    { count: '33', year: '1989' },
    { count: '33', year: '1988' }
];
//to get this
var data = [
    { count: '1', year: '1971' },
    { count: '12', year: '1956' },
    { count: '33', year: '1988' },
    { count: '33', year: '1989' },
];
8个回答

108

一个简单的解决方案是:

data.sort(function (a, b) {
  return a.count - b.count || a.year - b.year;
});

这个方法有效的原因是,如果count不同,那么排序就基于它。如果count相同,则第一个表达式返回0,转换为false,并使用第二个表达式的结果(即基于year排序)。


8
很好的使用0作为falsey! - The Qodesmith
9
数据.sort((a,b)=>(a.count - b.count || a.year - b.year)); - Jakob E

101

(查看jsfiddle)

var data = [
    { count: '12', year: '1956' },
    { count: '1', year: '1971' },
    { count: '33', year: '1989' },
    { count: '33', year: '1988' }
];

console.log(data.sort(function (x, y) {
    var n = x.count - y.count;
    if (n !== 0) {
        return n;
    }

    return x.year - y.year;
}));


56
数据排序:data.sort(function (x, y) { return x.count - y.count || x.year - y.year; });。此行代码会根据 count 属性和 year 属性对 data 数组进行排序。 - Luca Steeb

16

您可以使用 JavaScript 的 .sort() 数组方法(在此尝试一下):

data.sort(function(a, b) {
    // Sort by count
    var dCount = a.count - b.count;
    if(dCount) return dCount;

    // If there is a tie, sort by year
    var dYear = a.year - b.year;
    return dYear;
});

注意:这会改变原始数组。如果您需要首先进行复制,可以这样做:

var dataCopy = data.slice(0);

请检查我在上面问题中的一行代码。 - Luca Steeb

12
根据出色的@RobG解决方案(链接),以下是一个通用函数,可使用JS2015中的技巧map + find按多个不同的属性进行排序:
let sortBy = (p, a) => a.sort((i, j) => p.map(v => i[v] - j[v]).find(r => r))

sortBy(['count', 'year'], data)

此外,如果您喜欢,还可以使用传统的JS版本(由于旧浏览器中的find兼容性问题,请谨慎使用):

var sortBy = function (properties, targetArray) {
  targetArray.sort(function (i, j) {
    return properties.map(function (prop) {
      return i[prop] - j[prop];
    }).find(function (result) {
      return result;
    });
  });
};

6

你需要按照以下方式解决这个问题

var customSort = function(name, type){
     return function(o, p){
         var a, b;
         if(o && p && typeof o === 'object' && typeof p === 'object'){
            a = o[name];
            b = p[name];
           if(a === b){
              return typeof type === 'function' ? type(o, p) : o;
           }

           if(typeof a=== typeof b){
              return a < b ? -1 : 1;
            }
          return typeof a < typeof b ? -1 : 1;
        }
     };

};

例如: 数据.sort(自定义排序('年份', 自定义排序('数量')));


这里加上一个可选的反转功能会更棒。 - mayankcpdixit

4

使用此查询时,'count'字段是第一优先级,'year'字段是第二优先级。

data.sort(function(a,b){
  return a['count']<b['count']?-1:(a['count']>b['count']?1:(a['year']<b['year']?-1:1));
});

1
如果您想按字母顺序而不是数字对字符串进行排序,这里有一个示例问题及其解决方案。
示例问题:数组的数组(finalArray),第一个条目为文件夹路径,第二个条目为文件名;排序以使数组首先按文件夹排序,对于相同的文件夹,再按文件名排序。
例如,在排序后,您可以期望得到:
[['folder1', 'abc.jpg'], 
 ['folder1', 'xyz.jpg'],
 ['folder2', 'def.jpg'],
 ['folder2', 'pqr.jpg']]

请参考Array.prototype.sort() - compareFunction

finalArray.sort((x: any, y: any): number => {
  const folder1: string = x[0].toLowerCase();
  const folder2: string = y[0].toLowerCase();
  const file1: string = x[1].toLowerCase();
  const file2: string = y[1].toLowerCase();

  if (folder1 > folder2) {
    return 1;
  } else if (folder1 === folder2 && file1 > file2) {
    return 1;
  } else if (folder1 === folder2 && file1 === file2) {
    return 0;
  } else if (folder1 === folder2 && file1 < file2) {
    return -1;
  } else if (folder1 < folder2) {
    return -1;
  }
});

记住,"Z"在 "a"之前(根据Unicode代码点首字母大写)这就是为什么我要使用 toLowerCase()。上述实现无法解决的问题是"10abc"将会排在"9abc"之前。

-4

只需执行:

array.sort((a,b)=>a[1]-b[1])

根据需要排序的索引,将括号内的1替换为相应的数字。

为了概括,让我添加下面的代码片段:

array.sort((a,b)=>a[i]-b[i])

我看到很多人使用完整的函数来实现这个,但其实一个简单的箭头函数就可以完成任务。

保持简单!

谢谢。


我认为这回答的是另一个问题。此答案适用于想要根据属性动态排序的人,本例中属性为 "i"。 OP想要在单个排序调用中按顺序对2个不同的列进行排序。 - Sean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接