簡體   English   中英

按字符串屬性值對對象數組進行排序

[英]Sort array of objects by string property value

我有一個 JavaScript 個對象的數組:

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

如何根據 JavaScript 中last_nom的值對它們進行排序?

我知道sort(a,b) ,但這似乎只適用於字符串和數字。 我需要向我的對象添加toString()方法嗎?

編寫自己的比較函數很容易:

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

您還可以創建一個動態排序函數,該函數根據您傳遞的對象的值對對象進行排序:

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");

在 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)
});

下划線.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' );

不知道為什么人們如此復雜:

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

對於更嚴格的引擎:

objs.sort(function(a, b){
  return a.last_nom == b.last_nom ? 0 : +(a.last_nom > b.last_nom) || -1;
});

交換運算符以按相反的字母順序對其進行排序。

區分大小寫

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);

如果您有重復的姓氏,則可以按名字對它們進行排序-

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;
});

截至 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;
});

使用原型繼承簡單快速地解決這個問題:

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"}]

更新:不再修改原始數組。

不正確的舊答案:

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()會將true轉換為1並將false轉換為0

Lodash.jsUnderscore.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來指定應該匹配的屬性的路徑。 我們將按嵌套的年齡屬性對用戶對象進行排序。 是的,它允許嵌套屬性匹配!

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); 

您可以使用最簡單的方法: Lodash

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

此方法類似於_.sortBy ,不同之處在於它允許指定要排序的迭代對象的排序順序。 如果未指定 orders,則所有值都按升序排序。 否則,為相應值的降序指定“desc”或“asc”為升序排序。

論據

集合(數組|對象):要迭代的集合。 [iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]): 要排序的迭代對象。 [orders] (string[]):迭代的排序順序。

退貨

(Array):返回新的排序數組。


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']);

我還沒有看到建議的這種特殊方法,所以這是我喜歡使用的一種簡潔的比較方法,它適用於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));

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 中的工作方式, 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));

除了使用自定義比較函數,您還可以使用自定義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();

這里有很多很好的答案,但我想指出,它們可以非常簡單地擴展以實現更復雜的排序。 您唯一需要做的就是使用 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_nom有兩個步驟, first_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 可以帶您走很長一段路,而無需外部庫或復雜代碼。 它也非常有效,因為不必進行字符串解析

嘗試這個,

UPTO 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;
});


IN ES6 & above:

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

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

示例用法:

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;
  };
};

我知道這個問題太老了,但我沒有看到任何類似於我的實現。
此版本基於Schwartzian 變換習語

function sortByAttribute(array, ...attrs) {
  // generate an array of predicate-objects contains
  // 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'));

為什么不寫短代碼?

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

排序(更多)復雜的對象數組

由於您可能會遇到像這個數組這樣更復雜的數據結構,我將擴展解決方案。

TL;博士

是基於@ege-Özcan非常可愛的答案的更多可插拔版本。

問題

我遇到了以下問題,無法更改。 我也不想暫時壓平物體。 我也不想使用下划線/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 上的工作示例

使用 JavaScript sort方法

可以修改sort方法以使用比較函數對數字、字符串甚至對象數組等任何內容進行排序。

比較函數作為可選參數傳遞給 sort 方法。

此比較函數接受 2 個參數,通常稱為ab 基於這 2 個參數,您可以修改排序方法以根據需要工作。

  1. 如果 compare 函數返回小於 0,則sort()方法在比b低的索引處對a進行排序。 簡單地說,a 將出現在 b 之前。
  2. 如果比較函數返回等於 0,則sort()方法將元素位置保持原樣。
  3. 如果比較函數返回大於 0,則sort()方法在比b更大的索引處對a進行排序。 只是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)
輸出

另一種選擇:

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));

默認按升序排序。

一個簡單的方法:

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

看到'.toLowerCase()'是必要的,以防止在比較字符串時出錯。

警告!
不建議使用此解決方案,因為它不會導致排序數組。 它留在這里供將來參考,因為這個想法並不罕見。

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

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;
}

Ege Özcan代碼的附加 desc 參數

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;
    }
}

將 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");

給定原始示例:

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<ba==ba>b分別返回 -1,0,1 。
  • || 在最后一行中, last_nom優先於first_nom
  • 減法適用於數字字段: var age_order = left.age - right.age;
  • 取反順序, return -last_nom_order || -first_nom_order || -age_order; return -last_nom_order || -first_nom_order || -age_order;

一個按屬性對對象數組進行排序的簡單函數

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
function compare(propName) {
    return function(a,b) {
        if (a[propName] < b[propName])
            return -1;
        if (a[propName] > b[propName])
            return 1;
        return 0;
    };
}

objs.sort(compare("last_nom"));

使用 Ramda,

npm 安裝 ramda

import R from 'ramda'
var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];
var ascendingSortedObjs = R.sortBy(R.prop('last_nom'), objs)
var descendingSortedObjs = R.reverse(ascendingSortedObjs)

您可以使用可重用的排序功能。

Array.prototype.order = function (prop, methods = {}) {
    if (prop?.constructor == Object) {
        methods = prop;
        prop = null;
    }
    const [orderType_a, orderType_b] = methods.reverse ? [1, -1] : [-1, 1];

    const $ = x => prop
        ? methods.insensitive
            ? String(x[prop]).toLowerCase()
            : x[prop]
        : methods.insensitive
            ? String(x).toLowerCase()
            : x;

    const fn = (a, b) => $(a) < $(b) ? orderType_a : $(b) < $(a) ? orderType_b : 0;
    return this.sort(fn);
};

它可用於對數組中的數組對象進行排序
.

let items = [{ x: "Z" }, 3, "1", "0", 2, { x: "a" }, { x: 0 }];
items
    .order("x", { insensitive: 1 })
    // [ { x: 0 }, { x: 'a' }, 3, '1', '0', 2, { x: 'Z' } ]
    .order({ reverse: 1 })
    // [ { x: 0 }, { x: 'a' }, 3, 2, { x: 'Z' }, '1', '0' ]
    .sort(x => typeof x == "string" || typeof x == "number" ? -1 : 0)
    // [ '0', '1', 2, 3, { x: 0 }, { x: 'a' }, { x: 'Z' } ]

第一個(可選) > 對包含在數組中的對象進行排序。
第二個是方法> { reverse: any, insensitive: any }

根據您的示例,您需要按兩個字段(姓氏,名字)排序,而不是一個。 您可以使用Alasql庫在一行中進行這種排序:

var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);

在 jsFiddle試試這個例子。

這是一個簡單的問題,不知道為什么人們有這么復雜的解決方案。
一個簡單的排序函數(基於快速排序算法):

function sortObjectsArray(objectsArray, sortKey)
        {
            // Quick Sort:
            var retVal;

            if (1 < objectsArray.length)
            {
                var pivotIndex = Math.floor((objectsArray.length - 1) / 2);  // middle index
                var pivotItem = objectsArray[pivotIndex];                    // value in the middle index
                var less = [], more = [];

                objectsArray.splice(pivotIndex, 1);                          // remove the item in the pivot position
                objectsArray.forEach(function(value, index, array)
                {
                    value[sortKey] <= pivotItem[sortKey] ?                   // compare the 'sortKey' proiperty
                        less.push(value) :
                        more.push(value) ;
                });

                retVal = sortObjectsArray(less, sortKey).concat([pivotItem], sortObjectsArray(more, sortKey));
            }
            else
            {
                retVal = objectsArray;
            }

            return retVal;
        }

使用示例:

var myArr = 
        [
            { val: 'x', idx: 3 },
            { val: 'y', idx: 2 },
            { val: 'z', idx: 5 },
        ];
myArr = sortObjectsArray(myArr, 'idx');

您可能需要將它們轉換為小寫以防止混淆。

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

})

方式1:

您可以使用Underscore.js 先導入下划線。

 import * as _ from 'underscore';
 let SortedObjs = _.sortBy(objs, 'last_nom');

方式2:使用比較功能。

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

objs.sort(compare);

簡單的回答:

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

細節:

今天很簡單,你可以用localeCompare比較字符串。 正如 Mozilla Doc 所說:

localeCompare()方法返回一個數字,指示引用字符串是在排序順序beforeafter還是is the same as the given string in sort order

    //example1:
    console.log("aaa".localeCompare("aab")); //-1
    console.log("aaa".localeCompare("aaa")); //0
    console.log("aab".localeCompare("aaa")); //1

    //example2:
    const a = 'réservé'; // with accents, lowercase
    const b = 'RESERVE'; // no accents, uppercase

    console.log(a.localeCompare(b));
    // expected output: 1
    console.log(a.localeCompare(b, 'en', { sensitivity: 'base' }));
    // expected output: 0

有關更多詳細信息,請參閱 Mozilla 文檔localeCompare

這個對我有用。 在這里它將保持未定義到最后。

 function sort(items, property, direction) { function compare(a, b) { if(!a[property] && !b[property]) { return 0; } else if(a[property] && !b[property]) { return -1; } else if(!a[property] && b[property]) { return 1; } else { const value1 = a[property].toString().toUpperCase(); // ignore upper and lowercase const value2 = b[property].toString().toUpperCase(); // ignore upper and lowercase if (value1 < value2) { return direction === 0 ? -1 : 1; } else if (value1 > value2) { return direction === 0 ? 1 : -1; } else { return 0; } } } return items.sort(compare); } var items = [ { name: 'Edward', value: 21 }, { name: 'Sharpe', value: 37 }, { name: 'And', value: 45 }, { name: 'The', value: -12 }, { name: undefined, value: -12 }, { name: 'Magnetic', value: 13 }, { name: 'Zeros', value: 37 } ]; console.log('Ascending Order:- '); console.log(sort(items, 'name', 0)); console.log('Decending Order:- '); console.log(sort(items, 'name', 1));

當您想要自然排序(即1,2,10,11,111 )時,使用Intl.Collator對特定情況下的對象進行排序。

 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);

瀏覽器對Intl.Collator的支持

使用xPrototypehttps ://github.com/reduardo7/xPrototype/blob/master/README.md#sortbycol1-col2-coln

var o = [ 
  { Name: 'Lazslo', LastName: 'Jamf'     },
  { Name: 'Pig',    LastName: 'Bodine'   },
  { Name: 'Pirate', LastName: 'Prentice' },
  { Name: 'Pag',    LastName: 'Bodine'   }
];


// Original
o.each(function (a, b) { console.log(a, b); });
/*
 0 Object {Name: "Lazslo", LastName: "Jamf"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Pirate", LastName: "Prentice"}
 3 Object {Name: "Pag", LastName: "Bodine"}
*/


// Sort By LastName ASC, Name ASC
o.sortBy('LastName', 'Name').each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pag", LastName: "Bodine"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Lazslo", LastName: "Jamf"}
 3 Object {Name: "Pirate", LastName: "Prentice"}
*/


// Sort by LastName ASC and Name ASC
o.sortBy('LastName'.asc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pag", LastName: "Bodine"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Lazslo", LastName: "Jamf"}
 3 Object {Name: "Pirate", LastName: "Prentice"}
*/


// Sort by LastName DESC and Name DESC
o.sortBy('LastName'.desc, 'Name'.desc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pirate", LastName: "Prentice"}
 1 Object {Name: "Lazslo", LastName: "Jamf"}
 2 Object {Name: "Pig", LastName: "Bodine"}
 3 Object {Name: "Pag", LastName: "Bodine"}
*/


// Sort by LastName DESC and Name ASC
o.sortBy('LastName'.desc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pirate", LastName: "Prentice"}
 1 Object {Name: "Lazslo", LastName: "Jamf"}
 2 Object {Name: "Pag", LastName: "Bodine"}
 3 Object {Name: "Pig", LastName: "Bodine"}
*/

我剛剛增強了Ege Özcan的動態排序以深入對象內部。 如果數據看起來像這樣:

obj = [
    {
        a: { a: 1, b: 2, c: 3 },
        b: { a: 4, b: 5, c: 6 }
    },
    { 
        a: { a: 3, b: 2, c: 1 },
        b: { a: 6, b: 5, c: 4 }
}];

如果您想通過aa屬性對其進行排序,我認為我的增強功能非常有用。 我向這樣的對象添加新功能:

Object.defineProperty(Object.prototype, 'deepVal', {
    enumerable: false,
    writable: true,
    value: function (propertyChain) {
        var levels = propertyChain.split('.');
        parent = this;
        for (var i = 0; i < levels.length; i++) {
            if (!parent[levels[i]])
                return undefined;
            parent = parent[levels[i]];
        }
        return parent;
    }
});

並更改了_dynamicSort返回函數:

return function (a,b) {
        var result = ((a.deepVal(property) > b.deepVal(property)) - (a.deepVal(property) < b.deepVal(property)));
        return result * sortOrder;
    }

現在您可以通過這種方式按aa排序:

obj.sortBy('a.a');

請參閱JSFiddle中的完整腳本

使用 lodash 或 Underscore,它是小菜一碟

> const sortedList = _.orderBy(objs, [last_nom], [asc]); // asc or desc

我一直在各種項目中使用此實用程序,並且效果很好。 它也非常模塊化:

  • 傳遞要排序的鍵名
  • 選擇排序是升序還是降序

sortArrayOfObjsByKeyUtil.js

// Sort array of objects by key
// ------------------------------------------------------------
const sortArrayOfObjsByKey = (array, key, ascdesc) =>
  array.sort((a, b) => {
    const x = a[key];
    const y = b[key];
    if (ascdesc === 'asc') {
      return x < y ? -1 : x > y ? 1 : 0;
    }
    if (ascdesc === 'desc') {
      return x > y ? -1 : x < y ? 1 : 0;
    }
    return null;
  });

sortArrayOfObjsByKeyUtil.test.js

import sortArrayOfObjsByKey from './sortArrayOfObjsByKeyUtil';

const unsortedArray = [
  {
    _id: '3df55221-ce5c-4147-8e14-32effede6133',
    title: 'Netlife Design',
    address: {
      PostalAddress: {
        streetAddress: 'Youngstorget 3',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0181',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.914322, lng: 10.749272 },
  },
  {
    _id: 'cd00459f-3755-49f1-8847-66591ef935b2',
    title: 'Home',
    address: {
      PostalAddress: {
        streetAddress: 'Stockfleths gate 58A',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0461',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.937316, lng: 10.751862 },
  },
];

const sortedArray = [
  {
    _id: 'cd00459f-3755-49f1-8847-66591ef935b2',
    title: 'Home',
    address: {
      PostalAddress: {
        streetAddress: 'Stockfleths gate 58A',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0461',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.937316, lng: 10.751862 },
  },
  {
    _id: '3df55221-ce5c-4147-8e14-32effede6133',
    title: 'Netlife Design',
    address: {
      PostalAddress: {
        streetAddress: 'Youngstorget 3',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0181',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.914322, lng: 10.749272 },
  },
];

describe('sortArrayOfObjsByKey', () => {
  it(`sort array by 'title' key, ascending`, () => {
    const testInput = sortArrayOfObjsByKey(unsortedArray, 'title', 'asc');
    const testOutput = sortedArray;
    expect(testInput).toEqual(testOutput);
  });
});

TypeScript中編程時也可以創建動態排序功能,但在這種情況下類型變得更加棘手。

function sortByKey<O>(key: keyof O, decending: boolean = false): (a: O, b: O) => number {
    const order = decending ? -1 : 1;
    return (a, b): number => {
        const valA = a[key];
        const valB = b[key];
        if (valA < valB) {
            return -order;
        } else if (valA > valB) {
            return order;
        } else {
            return 0;
        }
    }
}

這可以在 TypeScript 中使用,如下所示:

const test = [
    {
        id: 0,
    },
    {
        id: 2,
    }
]

test.sort(sortByKey('id')) // OK
test.sort(sortByKey('id1')) // ERROR
test.sort(sortByKey('')) // ERROR

此排序功能可用於所有對象排序,

  • 目的

  • 深度對象

  • 數值數組

您還可以通過將 1,-1 作為參數傳遞來進行 assending 或 desending 排序

 Object.defineProperty(Object.prototype, 'deepVal', { enumerable: false, writable: true, value: function (propertyChain) { var levels = propertyChain.split('.'); parent = this; for (var i = 0; i < levels.length; i++) { if (!parent[levels[i]]) return undefined; parent = parent[levels[i]]; } return parent; } }); function dynamicSortAll(property,sortOrders=1) { /**default sorting will be ascending order if you need descending order sording you have to pass -1 as param**/ var sortOrder = sortOrders; return function (a,b) { var result =(property? ((a.deepVal(property) > b.deepVal(property)) ? 1 : (a.deepVal(property) < b.deepVal(property)) ? -1 : 0) :((a > b) ? 1 : (a < b) ? -1 : 0)) return result * sortOrder; } } deepObj = [ { a: { a: 1, b: 2, c: 3 }, b: { a: 4, b: 5, c: 6 } }, { a: { a: 3, b: 2, c: 1 }, b: { a: 6, b: 5, c: 4 } }]; let deepobjResult=deepObj.sort(dynamicSortAll('a.a',1)) console.log('deepobjResult :'+ JSON.stringify(deepobjResult)) var obj = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; let objResult=obj.sort(dynamicSortAll('last_nom',1)) console.log('objResult :'+ JSON.stringify(objResult)) var numericObj=[1,2,3,4,5,6] let numResult=numericObj.sort(dynamicSortAll(null,-1)) console.log('numResult :'+ JSON.stringify(numResult)) let stringSortResult='helloworld'.split('').sort(dynamicSortAll(null,1)) console.log('stringSortResult:'+ JSON.stringify(stringSortResult)) let uniqueStringOrger=[...new Set(stringSortResult)]; console.log('uniqueStringOrger:'+ JSON.stringify(uniqueStringOrger))

深的

基於這個優秀的教程,我想開發Vlad Bezden 的答案並解釋為什么localeComparestrA > strB等標准comarison方法更好。 讓我們運行這個例子

 console.log( 'Österreich' > 'Zealand' ); // We expect false console.log( 'a' > 'Z' ); // We expect false

原因是在 JS 中所有字符串都使用UTF-16編碼,並且

 let str = ''; // order of characters in JS for (let i = 65; i <= 220; i++) { str += String.fromCodePoint(i); // code to character } console.log(str);

大寫字母在前(有小代碼),然后是小寫字母,然后是字符Ö (在z之后)。 這就是為什么我們在第一個片段中得到正確的原因 - 因為運算符>比較字符代碼。

正如您所見,比較不同語言中的字符並非易事——但幸運的是,現代瀏覽器支持國際化標准ECMA-402 所以在 JS 中我們有strA.localeCompare(strB)來完成這項工作( -1表示strA小於strB ;1 表示相反;0 表示相等)

 console.log( 'Österreich'.localeCompare('Zealand') ); // We expect -1 console.log( 'a'.localeCompare('Z') ); // We expect -1

我想補充一點, localeCompare支持兩個參數:語言和附加規則

 var objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' }, { first_nom: 'Test', last_nom: 'jamf' } ]; objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom,'en',{sensitivity:'case'})) console.log(objs); // in '>' comparison 'Jamf' will NOT be next to 'jamf'

我遇到了對對象數組進行排序的問題,隨着值的優先級發生變化,基本上我想按人的年齡對數組進行排序,然后按姓氏 - 或者只是按姓氏,名字。 我認為與其他答案相比,這是最簡單的解決方案。

它通過調用 sortPeoples(['array', 'of', 'properties'], reverse=false) 來使用

 ///////////////////////example array of peoples /////////////////////// var peoples = [ {name: "Zach", surname: "Emergency", age: 1}, {name: "Nancy", surname: "Nurse", age: 1}, {name: "Ethel", surname: "Emergency", age: 1}, {name: "Nina", surname: "Nurse", age: 42}, {name: "Anthony", surname: "Emergency", age: 42}, {name: "Nina", surname: "Nurse", age: 32}, {name: "Ed", surname: "Emergency", age: 28}, {name: "Peter", surname: "Physician", age: 58}, {name: "Al", surname: "Emergency", age: 58}, {name: "Ruth", surname: "Registration", age: 62}, {name: "Ed", surname: "Emergency", age: 38}, {name: "Tammy", surname: "Triage", age: 29}, {name: "Alan", surname: "Emergency", age: 60}, {name: "Nina", surname: "Nurse", age: 58} ]; //////////////////////// Sorting function ///////////////////// function sortPeoples(propertyArr, reverse) { function compare(a,b) { var i=0; while (propertyArr[i]) { if (a[propertyArr[i]] < b[propertyArr[i]]) return -1; if (a[propertyArr[i]] > b[propertyArr[i]]) return 1; i++; } return 0; } peoples.sort(compare); if (reverse){ peoples.reverse(); } }; ////////////////end of sorting method/////////////// function printPeoples(){ $('#output').html(''); peoples.forEach( function(person){ $('#output').append(person.surname+" "+person.name+" "+person.age+"<br>"); } ) }
 <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> </head> <html> <body> <button onclick="sortPeoples(['surname']); printPeoples()">sort by ONLY by surname ASC results in mess with same name cases</button><br> <button onclick="sortPeoples(['surname', 'name'], true); printPeoples()">sort by surname then name DESC</button><br> <button onclick="sortPeoples(['age']); printPeoples()">sort by AGE ASC. Same issue as in first case</button><br> <button onclick="sortPeoples(['age', 'surname']); printPeoples()">sort by AGE and Surname ASC. Adding second field fixed it.</button><br> <div id="output"></div> </body> </html>

// Sort Array of Objects

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

// Property to Sort By
var args = "last_nom";

// Function to Sort the Data by given Property
function sortByProperty(property) {
    return function (a, b) {
        var sortStatus = 0,
            aProp = a[property].toLowerCase(),
            bProp = b[property].toLowerCase();
        if (aProp < bProp) {
            sortStatus = -1;
        } else if (aProp > bProp) {
            sortStatus = 1;
        }
        return sortStatus;
    };
}

// Implementation
var sortedArray = booksArray.sort(sortByProperty(args));

console.log("sortedArray: " + JSON.stringify(sortedArray) );

控制台日志輸出:

"sortedArray: 
[{"first_nom":"Pig","last_nom":"Bodine"},
{"first_nom":"Lazslo","last_nom":"Jamf"},
{"first_nom":"Pirate","last_nom":"Prentice"}]"

基於此來源改編: https ://web.archive.org/web/20210515081841/http://opnsrce.github.io/code-snippet-how-to-sort-an-array-of-json-objects- 副業

這將通過按字母數字順序傳遞給它的屬性對兩級嵌套數組進行排序。

function sortArrayObjectsByPropAlphaNum(property) {
    return function (a,b) {
        var reA = /[^a-zA-Z]/g;
        var reN = /[^0-9]/g;
        var aA = a[property].replace(reA, '');
        var bA = b[property].replace(reA, '');

        if(aA === bA) {
            var aN = parseInt(a[property].replace(reN, ''), 10);
            var bN = parseInt(b[property].replace(reN, ''), 10);
            return aN === bN ? 0 : aN > bN ? 1 : -1;
        } else {
            return a[property] > b[property] ? 1 : -1;
        }
    };
}

用法:

objs.sort(utils.sortArrayObjectsByPropAlphaNum('last_nom'));

所以這是一種排序算法,它可以在任何類型的對象數組中以任何順序排序,不受數據類型比較(即數字、字符串)的限制。

function smoothSort(items,prop,reverse) {  
    var length = items.length;
    for (var i = (length - 1); i >= 0; i--) {
        //Number of passes
        for (var j = (length - i); j > 0; j--) {
            //Compare the adjacent positions
            if(reverse){
              if (items[j][prop] > items[j - 1][prop]) {
                //Swap the numbers
                var tmp = items[j];
                items[j] = items[j - 1];
                items[j - 1] = tmp;
            }
            }

            if(!reverse){
              if (items[j][prop] < items[j - 1][prop]) {
                  //Swap the numbers
                  var tmp = items[j];
                  items[j] = items[j - 1];
                  items[j - 1] = tmp;
              }
            }
        }
    }

    return items;
}
  • 第一個參數items是對象數組,

  • prop是要排序的對象的鍵,

  • reverse是一個布爾參數,如果為真,則按升序排列,如果為假,則返回降序。

她的函數可以用來按多個對象對列表進行排序,如果第一個對象相等,則第二個順序將用作后備。 如果可能,空值也應忽略回退順序。

function sortObjects(list, orderBy){
    list.sort(function(a, b){
        let byIndex = 0;
        let order = orderBy[byIndex];
        while(!a[order.by] || !b[order.by] || a[order.by] === b[order.by]){
            byIndex++;
            if(byIndex >= orderBy.length){break;}
            order = orderBy[byIndex];
        }
        if(!a[order.by] || !b[order.by] || a[order.by] === b[order.by]){
            return false;
        }
        if(order.desc){
            return a[order.by] < b[order.by];
        }
        return a[order.by] > b[order.by];
    });
    return list;
}

用法:

var objs = [
    {a: 10, b: 20, c: 30},
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
];

sortObjectList(objs, [{by: 'a'}]);
[
    {a: 10, b: 20, c: 30},
    {a: 20, b: 10, c: 30},
    {a: 30, b: 10, c: 20},
]

sortObjectList(objs, [{by: 'a', desc: true}]);
[
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
    {a: 10, b: 20, c: 30},
]

sortObjectList(objs, [{by: 'b', desc: true}, {by: 'c'}]);
[
    {a: 10, b: 20, c: 30},
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
]

另一個例子:

var objs = [
    {a: 5, b: 5},
    {a: 10, b: 15},
    {a: 15, b: 25},
    {b: 10},
    {b: 20},
    {a: 10, b: 30},
    {a: 10, b: 12},
];

sortObjectList(objs, [{by: 'a'}, {by: 'b'}]);
[
    {a: 5, b: 5},
    {b: 10},
    {a: 10, b: 12},
    {a: 10, b: 15},
    {b: 20},
    {a: 10, b: 30},
    {a: 15, b: 25},
]

對於 fp-holics:

const objectSorter = (p)=>(a,b)=>((a,b)=>a>b?1:a<b?-1:0)(a[p], b[p]);
objs.sort(objectSorter('first_nom'));

我會給你一個實現選擇排序算法的解決方案,它簡單有效

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


function selection_Sort(num) { 
 //console.log(num);  
 var temp, index;
 for (var i = 0; i <= num.length - 1; i++) {
index = i;
for (var j = i + 1; j <= num.length - 1; j++) {
 // you can use first_nom/last_nom,any way you choose to sort

  if (num[j]. last_nom < num[index]. last_nom) {
    index = j;
  } 
}

//below is the swapping part
temp = num[i]. last_nom;
num[i]. last_nom = num[index]. last_nom;
num[index]. last_nom = temp;
 };
 console.log(num); 
 return num; 
  }
  selection_Sort(objs);

很高興看到這么好的答案

如果您有嵌套對象

const objs = [{
        first_nom: 'Lazslo',
        last_nom: 'Jamf',
        moreDetails: {
            age: 20
        }
    }, {
        first_nom: 'Pig',
        last_nom: 'Bodine',
        moreDetails: {
            age: 21
        }
    }, {
        first_nom: 'Pirate',
        last_nom: 'Prentice',
        moreDetails: {
            age: 22
        }
    }];

nestedSort = (prop1, prop2 = null, direction = 'asc') => (e1, e2) => {
        const a = prop2 ? e1[prop1][prop2] : e1[prop1],
            b = prop2 ? e2[prop1][prop2] : e2[prop1],
            sortOrder = direction === "asc" ? 1 : -1
        return (a < b) ? -sortOrder : (a > b) ? sortOrder : 0;
    }

並稱它為

objs.sort(nestedSort("last_nom"));
objs.sort(nestedSort("last_nom", null, "desc"));
objs.sort(nestedSort("moreDetails", "age"));
objs.sort(nestedSort("moreDetails", "age", "desc"));
//Try this way


let objs = [ 
        { first_nom: 'Lazslo', last_nom: 'Jamf'     },
        { first_nom: 'Pig',    last_nom: 'Bodine'   },
        { first_nom: 'Pirate', last_nom: 'Prentice' }
    ];
    const compareBylastNom = (a, b) => {
        // converting to uppercase to have case-insensitive comparison
        const name1 = a.last_nom.toUpperCase();
        const name2 = b.last_nom.toUpperCase();
    
        let comparison = 0;
    
        if (name1 > name2) {
            comparison = 1;
        } else if (name1 < name2) {
            comparison = -1;
        }
        return comparison;
    }
    console.log(objs.sort(compareBylastNom));

我知道已經有很多答案,包括那些帶有 localeCompare 的答案,但是如果您出於某種原因不想/不能使用 localeCompare,我建議您使用此解決方案而不是三元運算符解決方案:

objects.sort((a, b) => (a.name > b.name) - (a.name < b.name));

有人可能會說這段代碼在做什么並不明顯,但在我看來,三元運算符更糟。 如果一個三元運算符足夠可讀,則兩個三元運算符一個嵌入另一個 - 真的很難閱讀和丑陋。 只有兩個比較運算符和一個減號運算符的一行代碼非常易於閱讀和推理。

let propName = 'last_nom';

let sorted_obj = objs.sort((a,b) => {
    if(a[propName] > b[propName]) {
        return 1;
    }
    if (a[propName] < b[propName]) {
        return -1;
    }
    return 0;
}

//This works because the js built-in sort function allows us to define our
//own way of sorting, this funny looking function is simply telling `sort` how to
//determine what is larger. 
//We can use `if(a[propName] > b[propName])` because string comparison is already built into JS
//if you try console.log('a' > 'z' ? 'a' : 'z')
//the output will be 'z' as 'a' is not greater than 'z'

我會這樣做:

[...objs].sort((a, b) => a.last_nom.localeCompare(b.last_nom))
  var objs = [ 
    { firstName: 'A', lastName: 'Mark'  }, // b
    { firstName: 'E', lastName: 'askavy' }, // a
    { firstName: 'C', lastName: 'peter' }
];

objs.sort((a,b) => {
   return a.firstName.localeCompare(b.firstName) // Sort Ascending 
}) 

objs.sort((a,b) => {
   return b.firstName.localeCompare(a.firstName) // Sort Decending
}) 

 console.log(objs)

我使用這個解決方案:

use yourArrayName.sort(); // ascending
use yourArrayName.sort().reverse(); // descending

我喜歡下面。

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

objs.sort(function(a, b) {
  const nameA = a.name.toUpperCase(); // ignore upper and lowercase
  const nameB = b.name.toUpperCase(); // ignore upper and lowercase
  if (nameA < nameB) {
    return -1;
  }
  if (nameA > nameB) {
    return 1;
  }
  // names must be equal
  return 0;
});

console.log(arr);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM