按字符串属性值对对象数组进行排序

2024-11-02 20:49:00
admin
原创
38
摘要:问题描述:我有一个 JavaScript 对象数组:var objs = [ { first_nom: 'Laszlo', last_nom: 'Jamf' }, { first_nom: 'P...

问题描述:

我有一个 JavaScript 对象数组:

var objs = [ 
    { first_nom: 'Laszlo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

我如何根据last_nomJavaScript 中的值对它们进行排序?

我知道sort(a,b),但这似乎只适用于字符串和数字。我需要toString()向对象添加方法吗?


解决方案 1:

编写自己的比较函数非常简单:

function compare( a, b ) {
  if ( a.last_nom < b.last_nom ){
    return -1;
  }
  if ( a.last_nom > b.last_nom ){
    return 1;
  }
  return 0;
}

objs.sort( compare );

或内联(c/o Marco Demaio):

objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0))

或者简化为数字(c/o Andre Figueiredo):

objs.sort((a,b) => a.last_nom - b.last_nom); // b - a for reverse sort

解决方案 2:

您还可以创建一个动态排序函数,根据您传递的值对对象进行排序:

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        /* next line works with strings and numbers, 
         * and you may want to customize it to your needs
         */
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

因此你可以拥有如下对象数组:

var People = [
    {Name: "Name", Surname: "Surname"},
    {Name:"AAA", Surname:"ZZZ"},
    {Name: "Name", Surname: "AAA"}
];

...当你这样做时它就会起作用:

People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));

其实这已经回答了这个问题。下面部分是因为很多人联系我,抱怨它不适用于多个参数。

多个参数

您可以使用下面的函数来生成具有多个排序参数的排序函数。

function dynamicSortMultiple() {
    /*
     * save the arguments object as it will be overwritten
     * note that arguments object is an array-like object
     * consisting of the names of the properties to sort by
     */
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        /* try getting a different result from 0 (equal)
         * as long as we have extra properties to compare
         */
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i])(obj1, obj2);
            i++;
        }
        return result;
    }
}

这将使你能够做这样的事情:

People.sort(dynamicSortMultiple("Name", "-Surname"));

子类化数组

对于我们这些幸运的人来说,可以使用 ES6,它允许扩展本机对象:

class MyArray extends Array {
    sortBy(...args) {
        return this.sort(dynamicSortMultiple(...args));
    }
}

这将实现这一点:

MyArray.from(People).sortBy("Name", "-Surname");

解决方案 3:

在ES6/ES2015或更高版本中,你可以这样做:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));

ES6/ES2015 之前

objs.sort(function(a, b) {
    return a.last_nom.localeCompare(b.last_nom)
});

解决方案 4:

Underscore.js

使用 Underscore.js。它很小而且很棒……

sortBy_.sortBy(list, iterator, [context]) 返回列表的排序副本,按通过迭代器运行每个值的结果按升序排列。迭代器也可以是排序属性的字符串名称(例如长度)。

var objs = [
  { first_nom: 'Lazslo',last_nom: 'Jamf' },
  { first_nom: 'Pig', last_nom: 'Bodine'  },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];

var sortedObjs = _.sortBy(objs, 'first_nom');

解决方案 5:

区分大小写

arr.sort((a, b) => a.name > b.name ? 1 : -1);

不区分大小写

arr.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1);

有用的提示

如果顺序没有变化(如果字符串相同),则条件>将失败并-1返回。但如果字符串相同,则返回 1 或 -1 将导致正确输出

另一种选择是使用>=运算符代替>


var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];


// Define a couple of sorting callback functions, one with hardcoded sort key and the other with an argument sort key
const sorter1 = (a, b) => a.last_nom.toLowerCase() > b.last_nom.toLowerCase() ? 1 : -1;
const sorter2 = (sortBy) => (a, b) => a[sortBy].toLowerCase() > b[sortBy].toLowerCase() ? 1 : -1;

objs.sort(sorter1);
console.log("Using sorter1 - Hardcoded sort property last_name", objs);

objs.sort(sorter2('first_nom'));
console.log("Using sorter2 - passed param sortBy='first_nom'", objs);

objs.sort(sorter2('last_nom'));
console.log("Using sorter2 - passed param sortBy='last_nom'", objs);

运行代码片段Hide results展开片段

解决方案 6:

如果您有重复的姓氏,您可以按名字排序 -

obj.sort(function(a,b){
  if(a.last_nom< b.last_nom) return -1;
  if(a.last_nom >b.last_nom) return 1;
  if(a.first_nom< b.first_nom) return -1;
  if(a.first_nom >b.first_nom) return 1;
  return 0;
});

解决方案 7:

截至 2018 年,有一个更简短、更优雅的解决方案。只需使用Array.prototype.sort()。

例子:

var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) {
  return a.value - b.value;
});

解决方案 8:

使用原型继承可以简单快速地解决这个问题:

Array.prototype.sortBy = function(p) {
  return this.slice(0).sort(function(a,b) {
    return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
  });
}

示例/用法

objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}];

objs.sortBy('age');
// Returns
// [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}]

objs.sortBy('name');
// Returns
// [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}]

更新:不再修改原始数组。

解决方案 9:

不正确的旧答案:

arr.sort((a, b) => a.name > b.name)

更新

来自Beauchamp 的评论:

arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))

更易读的格式:

arr.sort((a, b) => {
  if (a.name < b.name) return -1
  return a.name > b.name ? 1 : 0
})

没有嵌套的三元运算符:

arr.sort((a, b) => a.name < b.name ? - 1 : Number(a.name > b.name))

解释:Number()将转换true1和。false`0`

解决方案 10:

您可以使用最简单的方法:Lodash

https://lodash.com/docs/4.17.10#orderBy

此方法与此类似_.sortBy,不同之处在于它允许指定迭代器的排序顺序。如果未指定顺序,则所有值均按升序排序。否则,指定“desc”以表示降序,或指定“asc”以表示相应值的升序排序。

参数

collection (Array|Object):要迭代的集合。[iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]):要排序的迭代器。[orders] (string[]):迭代器的排序顺序。

返回

(数组):返回新的排序数组。


var _ = require('lodash');
var homes = [
    {"h_id":"3",
     "city":"Dallas",
     "state":"TX",
     "zip":"75201",
     "price":"162500"},
    {"h_id":"4",
     "city":"Bevery Hills",
     "state":"CA",
     "zip":"90210",
     "price":"319250"},
    {"h_id":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];
    
_.orderBy(homes, ['city', 'state', 'zip'], ['asc', 'desc', 'asc']);

解决方案 11:

Lodash (Underscore.js的超集)。

最好不要为每个简单的逻辑添加一个框架,但是依靠经过充分测试的实用程序框架可以加快开发速度并减少错误数量。

Lodash 的代码非常简洁,并且提倡更函数式的编程风格。一眼望去,就能清楚地知道代码的意图。

OP的问题可以简单地这样解决:

const sortedObjs = _.sortBy(objs, 'last_nom');

更多信息?例如,我们有以下嵌套对象:

const users = [
  { 'user': {'name':'fred', 'age': 48}},
  { 'user': {'name':'barney', 'age': 36 }},
  { 'user': {'name':'wilma'}},
  { 'user': {'name':'betty', 'age': 32}}
];

现在,我们可以使用_.property简写user.age来指定应匹配的属性的路径。我们将按嵌套的 age 属性对用户对象进行排序。是的,它允许嵌套属性匹配!

const sortedObjs = _.sortBy(users, ['user.age']);

想要反转吗?没问题。使用_.reverse。

const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));

想要使用链条将两者结合起来吗?

const { chain } = require('lodash');
const sortedObjs = chain(users).sortBy('user.age').reverse().value();

或者什么时候您更喜欢流程而不是链式?

const { flow, reverse, sortBy } = require('lodash/fp');
const sortedObjs = flow([sortBy('user.age'), reverse])(users);

解决方案 12:

我还没有看到建议这种特殊的方法,因此这里有一个我喜欢使用的简洁的比较方法,它适用于stringnumber类型:

const objs = [ 
  { first_nom: 'Lazslo', last_nom: 'Jamf'     },
  { first_nom: 'Pig',    last_nom: 'Bodine'   },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];

const sortBy = fn => {
  const cmp = (a, b) => -(a < b) || +(a > b);
  return (a, b) => cmp(fn(a), fn(b));
};

const getLastName = o => o.last_nom;
const sortByLastName = sortBy(getLastName);

objs.sort(sortByLastName);
console.log(objs.map(getLastName));

运行代码片段Hide results展开片段

解释sortBy()

sortBy()接受一个fn,它从对象中选择一个值用于比较,并返回一个可以传递给的函数Array.prototype.sort()。在这个例子中,我们正在比较o.last_nom。每当我们收到两个对象,例如

a = { first_nom: 'Lazslo', last_nom: 'Jamf' }
b = { first_nom: 'Pig', last_nom: 'Bodine' }

我们将它们与进行比较(a, b) => cmp(fn(a), fn(b))。鉴于

fn = o => o.last_nom

我们可以将比较函数扩展为(a, b) => cmp(a.last_nom, b.last_nom)。由于JavaScript 中逻辑 OR ( ||) 的工作方式,cmp(a.last_nom, b.last_nom)因此相当于

if (a.last_nom < b.last_nom) return -1;
if (a.last_nom > b.last_nom) return 1;
return 0;

顺便说一下,在其他语言中,这被称为三向比较“宇宙飞船”(<=>)运算符。

最后,这是不使用箭头函数的 ES5 兼容语法:

显示代码片段

var objs = [ 
  { first_nom: 'Lazslo', last_nom: 'Jamf'     },
  { first_nom: 'Pig',    last_nom: 'Bodine'   },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];

function sortBy(fn) {
  function cmp(a, b) { return -(a < b) || +(a > b); }
  return function (a, b) { return cmp(fn(a), fn(b)); };
}

function getLastName(o) { return o.last_nom; }
var sortByLastName = sortBy(getLastName);

objs.sort(sortByLastName);
console.log(objs.map(getLastName));

Run code snippetHide resultsExpand snippet

解决方案 13:

除了使用自定义比较函数之外,您还可以创建具有自定义toString()方法的对象类型(由默认比较函数调用):

function Person(firstName, lastName) {
    this.firtName = firstName;
    this.lastName = lastName;
}

Person.prototype.toString = function() {
    return this.lastName + ', ' + this.firstName;
}

var persons = [ new Person('Lazslo', 'Jamf'), ...]
persons.sort();

解决方案 14:

这里有很多不错的答案,但我想指出的是,它们可以非常简单地扩展以实现更复杂的排序。您唯一要做的就是使用 OR 运算符链接比较函数,如下所示:

objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )

其中fn1,,,fn2... 是返回 [-1,0,1] 的排序函数。这会导致“按 fn1 排序”和“按 fn2 排序”,这几乎相当于 SQL 中的 ORDER BY。

该解决方案基于||运算符的行为,该运算符计算第一个可转换为 true 的计算表达式。

最简单的形式只有一个内联函数,如下所示:

// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )

分为两个步骤last_nomfirst_nom排序顺序如下:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) ||
                  a.first_nom.localeCompare(b.first_nom)  )

通用比较函数可能是这样的:

// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])

此函数可以扩展以支持数字字段、区分大小写、任意数据类型等。

您可以按排序优先级链接它们来使用它们:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> cmp(a,b, "last_nom") || cmp(a,b, "first_nom") )
// ORDER_BY last_nom, first_nom DESC
objs.sort((a,b)=> cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )
// ORDER_BY last_nom DESC, first_nom DESC
objs.sort((a,b)=> -cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )

这里的重点是,纯 JavaScript 和函数式方法可以让你无需外部库或复杂代码就能取得很大进展。它也非常有效,因为不需要进行字符串解析。

解决方案 15:

尝试一下:

最高至ES5
// Ascending sort
items.sort(function (a, b) {
   return a.value - b.value;
});


// Descending sort
items.sort(function (a, b) {
   return b.value - a.value;
});
在ES6及更高版本中
// Ascending sort
items.sort((a, b) => a.value - b.value);

// Descending sort
items.sort((a, b) => b.value - a.value);

解决方案 16:

使用 JavaScriptsort方法

可以修改该sort方法以使用比较函数对任何内容(例如数字数组、字符串甚至对象)进行排序。

比较函数作为可选参数传递给排序方法。

此比较函数接受 2 个参数,通常称为ab。根据这两个参数,您可以修改排序方法以根据需要工作。

  1. 如果比较函数返回小于 0,则该sort()方法将a排序在比b更低的索引处。简单来说,a 将排在 b 之前。

  2. 如果比较函数返回等于 0,则该sort()方法保留元素位置不变。

  3. 如果比较函数返回大于 0,则该sort()方法将a排序在比b更大的索引处。简单来说,a将排在b之后。

使用上述概念应用于您的对象,其中a将是您的对象属性。

var objs = [
  { first_nom: 'Lazslo', last_nom: 'Jamf' },
  { first_nom: 'Pig', last_nom: 'Bodine' },
  { first_nom: 'Pirate', last_nom: 'Prentice' }
];
function compare(a, b) {
  if (a.last_nom > b.last_nom) return 1;
  if (a.last_nom < b.last_nom) return -1;
  return 0;
}
objs.sort(compare);
console.log(objs)
// for better look use console.table(objs)

运行代码片段Hide results展开片段

输出

解决方案 17:

用法示例:

objs.sort(sortBy('last_nom'));

脚本:

/**
 * @description
 * Returns a function which will sort an
 * array of objects by the given key.
 *
 * @param  {String}  key
 * @param  {Boolean} reverse
 * @return {Function}
 */
const sortBy = (key, reverse) => {

  // Move smaller items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  const moveSmaller = reverse ? 1 : -1;

  // Move larger items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  const moveLarger = reverse ? -1 : 1;

  /**
   * @param  {*} a
   * @param  {*} b
   * @return {Number}
   */
  return (a, b) => {
    if (a[key] < b[key]) {
      return moveSmaller;
    }
    if (a[key] > b[key]) {
      return moveLarger;
    }
    return 0;
  };
};

解决方案 18:

编写简短代码:

objs.sort((a, b) => a.last_nom > b.last_nom ? 1 : -1)

解决方案 19:

我没有看到任何与我的类似的实现。此版本基于Schwartzian 变换习语。

function sortByAttribute(array, ...attrs) {
  // Generate an array of predicate-objects containing
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // Schwartzian transform idiom implementation. AKA "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i])
        result = -1;
      if (o1.compareValues[i] > o2.compareValues[i])
        result = 1;
      if (result *= predicates[i].descend)
        break;
    }
    return result;
  })
  .map(item => item.src);
}

下面是一个如何使用它的示例:

let games = [
  { name: 'Mashraki',          rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// Sort by one attribute
console.log(sortByAttribute(games, 'name'));
// Sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

解决方案 20:

当您想要进行自然字符串排序(即)Intl.Collator时,根据特定情况对对象进行排序。["1","2","10","11","111"]

const files = [
 {name: "1.mp3", size: 123},
 {name: "10.mp3", size: 456},
 {name: "100.mp3", size: 789},
 {name: "11.mp3", size: 123},
 {name: "111.mp3", size: 456},
 {name: "2.mp3", size: 789},
];

const naturalCollator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});

files.sort((a, b) => naturalCollator.compare(a.name, b.name));

console.log(files);

运行代码片段Hide results展开片段

注意:的undefined构造函数参数Intl.Collator代表语言环境,可以是明确的 ISO 639-1 语言代码(例如)en,也可以是系统默认语言环境(当)undefined

浏览器支持Intl.Collator

解决方案 21:

对(更多)复杂对象数组进行排序

由于您可能会遇到像此数组一样更复杂的数据结构,因此我会扩展解决方案。

总结

根据@ege-Özcan非常可爱的回答,有更多的可插入版本。

问题

我遇到了下面的情况,无法更改。我也不想暂时将对象扁平化。我也不想使用 underscore / lodash,主要是出于性能原因和自己实现的乐趣。

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

目标

目标是主要按照以下方式进行排序People.Name.name,其次按照People.Name.surname

障碍

现在,基本解决方案使用括号表示法来动态计算要排序的属性。不过,在这里,我们还必须动态构造括号表示法,因为您可能希望某些类似的东西People['Name.name']能够起作用 - 但事实并非如此。

People['Name']['name']另一方面,简单地执行是静态的,并且只允许您下降到第 n级。

解决方案

这里的主要补充是遍历对象树并确定您必须指定的最后一个叶子的值以及任何中间叶子的值。

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname']));
// Results in...
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
//   { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
//   { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]

// same logic as above, but strong deviation for dynamic properties 
function dynamicSort(properties) {
  var sortOrder = 1;
  // determine sort order by checking sign of last element of array
  if(properties[properties.length - 1][0] === "-") {
    sortOrder = -1;
    // Chop off sign
    properties[properties.length - 1] = properties[properties.length - 1].substr(1);
  }
  return function (a,b) {
    propertyOfA = recurseObjProp(a, properties)
    propertyOfB = recurseObjProp(b, properties)
    var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
    return result * sortOrder;
  };
}

/**
 * Takes an object and recurses down the tree to a target leaf and returns it value
 * @param  {Object} root - Object to be traversed.
 * @param  {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child']
 * @param  {Number} index - Must not be set, since it is implicit.
 * @return {String|Number}       The property, which is to be compared by sort.
 */
function recurseObjProp(root, leafs, index) {
  index ? index : index = 0
  var upper = root
  // walk down one level
  lower = upper[leafs[index]]
  // Check if last leaf has been hit by having gone one step too far.
  // If so, return result from last step.
  if (!lower) {
    return upper
  }
  // Else: recurse!
  index++
  // HINT: Bug was here, for not explicitly returning function
  // https://stackoverflow.com/a/17528613/3580261
  return recurseObjProp(lower, leafs, index)
}

/**
 * Multi-sort your array by a set of properties
 * @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child']
 * @return {Number} Number - number for sort algorithm
 */
function dynamicMultiSort() {
  var args = Array.prototype.slice.call(arguments); // slight deviation to base

  return function (a, b) {
    var i = 0, result = 0, numberOfProperties = args.length;
    // REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature
    // Consider: `.forEach()`
    while(result === 0 && i < numberOfProperties) {
      result = dynamicSort(args[i])(a, b);
      i++;
    }
    return result;
  }
}

例子

JSBin 上的工作示例

解决方案 22:

将 Ege 的动态解决方案与 Vinay 的想法结合起来,您会得到一个很好的稳健解决方案:

Array.prototype.sortBy = function() {
  function _sortByAttr(attr) {
    var sortOrder = 1;
    if (attr[0] == "-") {
      sortOrder = -1;
      attr = attr.substr(1);
    }
    return function(a, b) {
      var result = (a[attr] < b[attr]) ? -1 : (a[attr] > b[attr]) ? 1 : 0;
      return result * sortOrder;
    }
  }

  function _getSortFunc() {
    if (arguments.length == 0) {
      throw "Zero length arguments not allowed for Array.sortBy()";
    }
    var args = arguments;
    return function(a, b) {
      for (var result = 0, i = 0; result == 0 && i < args.length; i++) {
        result = _sortByAttr(args[i])(a, b);
      }
      return result;
    }
  }
  return this.sort(_getSortFunc.apply(null, arguments));
}

Usage:

  // Utility for printing objects
  Array.prototype.print = function(title) {
    console.log("************************************************************************");
    console.log("**** " + title);
    console.log("************************************************************************");
    for (var i = 0; i < this.length; i++) {
      console.log("Name: " + this[i].FirstName, this[i].LastName, "Age: " + this[i].Age);
    }
  }

// Setup sample data
var arrObj = [{
    FirstName: "Zach",
    LastName: "Emergency",
    Age: 35
  },
  {
    FirstName: "Nancy",
    LastName: "Nurse",
    Age: 27
  },
  {
    FirstName: "Ethel",
    LastName: "Emergency",
    Age: 42
  },
  {
    FirstName: "Nina",
    LastName: "Nurse",
    Age: 48
  },
  {
    FirstName: "Anthony",
    LastName: "Emergency",
    Age: 44
  },
  {
    FirstName: "Nina",
    LastName: "Nurse",
    Age: 32
  },
  {
    FirstName: "Ed",
    LastName: "Emergency",
    Age: 28
  },
  {
    FirstName: "Peter",
    LastName: "Physician",
    Age: 58
  },
  {
    FirstName: "Al",
    LastName: "Emergency",
    Age: 51
  },
  {
    FirstName: "Ruth",
    LastName: "Registration",
    Age: 62
  },
  {
    FirstName: "Ed",
    LastName: "Emergency",
    Age: 38
  },
  {
    FirstName: "Tammy",
    LastName: "Triage",
    Age: 29
  },
  {
    FirstName: "Alan",
    LastName: "Emergency",
    Age: 60
  },
  {
    FirstName: "Nina",
    LastName: "Nurse",
    Age: 54
  }
];

//Unit Tests
arrObj.sortBy("LastName").print("LastName Ascending");
arrObj.sortBy("-LastName").print("LastName Descending");
arrObj.sortBy("LastName", "FirstName", "-Age").print("LastName Ascending, FirstName Ascending, Age Descending");
arrObj.sortBy("-FirstName", "Age").print("FirstName Descending, Age Ascending");
arrObj.sortBy("-Age").print("Age Descending");

运行代码片段Hide results展开片段

解决方案 23:

还有一个选择:

var someArray = [...];

function generateSortFn(prop, reverse) {
    return function (a, b) {
        if (a[prop] < b[prop]) return reverse ? 1 : -1;
        if (a[prop] > b[prop]) return reverse ? -1 : 1;
        return 0;
    };
}

someArray.sort(generateSortFn('name', true));

它默认按升序排序。

解决方案 24:

一个简单的方法:

objs.sort(function(a,b) {
  return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});

请参阅'.toLowerCase()'有必要防止在比较字符串时出现错误。

解决方案 25:

警告!不建议

使用此解决方案,因为它不会产生排序数组。它留在这里以供将来参考,因为这个想法并不罕见。

objs.sort(function(a,b){return b.last_nom>a.last_nom})

解决方案 26:

这是我的看法:

order参数是可选的,默认为“ASC”,表示升序。

它适用于重音字符并且不区分大小写

注意:它排序并返回原始数组。

function sanitizeToSort(str) {
  return str
    .normalize('NFD')                   // Remove accented and diacritics
    .replace(/[/u0300-/u036f]/g, '')    // Remove accented and diacritics
    .toLowerCase()                      // Sort will be case insensitive
  ;
}

function sortByProperty(arr, property, order="ASC") {
  arr.forEach((item) => item.tempProp = sanitizeToSort(item[property]));
  arr.sort((a, b) => order === "ASC" ?
      a.tempProp > b.tempProp ?  1 : a.tempProp < b.tempProp ? -1 : 0
    : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ?  1 : 0
  );
  arr.forEach((item) => delete item.tempProp);
  return arr;
}

片段

function sanitizeToSort(str) {
  return str
    .normalize('NFD')                   // Remove accented characters
    .replace(/[/u0300-/u036f]/g, '')    // Remove diacritics
    .toLowerCase()
  ;
}

function sortByProperty(arr, property, order="ASC") {
  arr.forEach((item) => item.tempProp = sanitizeToSort(item[property]));
  arr.sort((a, b) => order === "ASC" ?
      a.tempProp > b.tempProp ?  1 : a.tempProp < b.tempProp ? -1 : 0
    : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ?  1 : 0
  );
  arr.forEach((item) => delete item.tempProp);
  return arr;
}

const rockStars = [
  { name: "Axl",
    lastname: "Rose" },
  { name: "Elthon",
    lastname: "John" },
  { name: "Paul",
    lastname: "McCartney" },
  { name: "Lou",
    lastname: "Reed" },
  { name: "freddie",             // Works on lower/upper case
    lastname: "mercury" },
  { name: "Ámy",                 // Works on accented characters too
    lastname: "winehouse"}

];

sortByProperty(rockStars, "name");

console.log("Ordered by name A-Z:");
rockStars.forEach((item) => console.log(item.name + " " + item.lastname));

sortByProperty(rockStars, "lastname", "DESC");

console.log("
Ordered by lastname Z-A:");
rockStars.forEach((item) => console.log(item.lastname + ", " + item.name));

运行代码片段Hide results展开片段

解决方案 27:

给出原始示例:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

按多个字段排序:

objs.sort(function(left, right) {
    var last_nom_order = left.last_nom.localeCompare(right.last_nom);
    var first_nom_order = left.first_nom.localeCompare(right.first_nom);
    return last_nom_order || first_nom_order;
});

笔记

  • a.localeCompare(b)得到普遍支持a<b,如果,a==b,分别返回 -1,0,1 a>b

  • ||最后一行的last_nom优先于first_nom

  • 减法适用于数值字段:var age_order = left.age - right.age;

  • 否定以反转顺序,return -last_nom_order || -first_nom_order || -age_order;

解决方案 28:

根据属性对对象数组进行排序的简单函数:

function sortArray(array, property, direction) {
    direction = direction || 1;
    array.sort(function compare(a, b) {
        let comparison = 0;
        if (a[property] > b[property]) {
            comparison = 1 * direction;
        } else if (a[property] < b[property]) {
            comparison = -1 * direction;
        }
        return comparison;
    });
    return array; // Chainable
}

用法:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

sortArray(objs, "last_nom"); // Asc
sortArray(objs, "last_nom", -1); // Desc

解决方案 29:

Ege Özcan 代码的附加描述参数:

function dynamicSort(property, desc) {
    if (desc) {
        return function (a, b) {
            return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0;
        }
    }
    return function (a, b) {
        return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
    }
}

解决方案 30:

您可能需要将它们转换为小写形式以避免混淆。

objs.sort(function (a, b) {

    var nameA = a.last_nom.toLowerCase(), nameB = b.last_nom.toLowerCase()

    if (nameA < nameB)
      return -1;
    if (nameA > nameB)
      return 1;
    return 0;  // No sorting
})
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用