web-dev-qa-db-ja.com

オブジェクトの配列を文字列プロパティ値でソートする

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()メソッドを追加する必要がありますか?

2272
Tyrone Slothrop

あなた自身の比較関数を書くのは十分簡単です:

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

渡した値でオブジェクトをソートする動的ソート関数を作成することもできます。

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

プロトタイプに追加する

バインド演算子 が到着するまで、これは許容できる 妥協 になる可能性があります。あなたはこのように Object.defineProperty を使うことができます( 実用例 ):

Object.defineProperty(Array.prototype, "sortBy", {
    enumerable: false,
    writable: true,
    value: function() {
        return this.sort(_dynamicSortMultiple.apply(null, arguments));
    }
});

プロトタイプを試すことでこれが可能になります。

People.sortBy("Name", "-Surname");
736
Ege Özcan

ES6/ES2015以降では、次のようにします。

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

underscore.js

アンダースコアを使用して、その小さくて素晴らしい...

sortBy_.sortBy(list、iterator、[context])リストのソートされたコピーを返します。イテレータを通して各値を実行した結果によって昇順にランク付けされます。イテレータはソートするプロパティの文字列名(例えばlength)でも構いません。

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' );
171
David Morrow

人々がそれをそれほど複雑にする理由を理解しないでください:

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

逆アルファベット順にソートするように演算子を交換します。

159
p3lim

姓が重複している場合は、姓でそれらを並べ替えることができます。

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

プロトタイプ継承を使用してこの問題を簡単に素早く解決する:

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

更新: /元の配列を修正しません。

42
Vinay Aggarwal

カスタム比較関数を使用する代わりに、カスタムの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();
27
Christoph

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;
});
26
0leg

Lodash.jsの上位集合 - 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']));

代わりに Chaining を使って両方を組み合わせたいですか?

const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();
21
Nico Van Belle

ここにはたくさんの良い答えがありますが、もっと複雑なソートを実現するためにそれらを単純に拡張できることを指摘したいと思います。あなたがしなければならない唯一のことはこのような比較関数を連鎖するためにOR演算子を使うことです:

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

fn1fn2、...は[-1,0,1]を返すソート関数です。これは "fn1によるソート"、 "fn2によるソート"になります。これはSQLのORDER BYとほぼ同じです。

この解決策は、 trueに変換できる最初の評価式 に評価される||演算子の動作に基づいています。

最も単純な形式 には、次のようなインライン関数が1つだけあります。

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

last_nomfirst_nomソート順の2つのステップがあると、次のようになります。

// 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は、外部のライブラリや複雑なコードがなくても長い道のりを歩むことができるということです。文字列の解析を行う必要がないため、これも非常に効果的です。

20
Tero Tolonen

使用例

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;
  };
};
19
Jamie Mason

あなたが使用することができます

最も簡単な方法: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']);
19
Jack

この特定のアプローチが提案されているのを見たことがないので、stringnumberの両方で機能する簡潔な比較方法を以下に示します。

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

const sortBy = fn => (a, b) => {
  const fa = fn(a)
  const fb = fn(b)
  return -(fa < fb) || +(fa > fb)
}
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を使用しているため、Array.prototype.sort()を介して2つのオブジェクトを受け取るときは常に

{ first_nom: 'Lazslo', last_nom: 'Jamf' }

そして

{ first_nom: 'Pig', last_nom: 'Bodine' }

を使用しております

(a, b) => {
  const fa = fn(a)
  const fb = fn(b)
  return -(fa < fb) || +(fa > fb)
}

それらを比較します。

fn = o => o.last_nomを思い出して、比較関数を同等のものに拡張できます。

(a, b) => {
  const fa = a.last_nom
  const fb = b.last_nom
  return -(fa < fb) || +(fa > fb)
}

論理OR ||演算子には、ここで非常に役立つ短絡機能があります。それがどのように機能するかのために、上記の関数の本体は

if (fa < fb) return -1
return +(fa > fb)

fa < fbの場合は-1を返し、そうでない場合はfa > fbの場合は+1を返しますが、fa == fbの場合はfa < fbおよびfa > fbfalseであるため、+0を返します。

追加のボーナスとして、矢印関数のないECMAScript 5に相当するものがありますが、残念ながらこれはより冗長です。

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

var sortBy = function (fn) {
  return function (a, b) {
    var fa = fn(a)
    var fb = fn(b)
    return -(fa < fb) || +(fa > fb)
  }
}

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

objs.sort(sortByLastName)
console.log(objs.map(getLastName))
17
Patrick Roberts

私は私のために働くコードの一部を持っています:

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

更新:常に動作するわけではないので、正しくありません:(

16
Damjan Pavlica

私はこの質問が古すぎることを知っていますが、私のような実装は見られませんでした。
このバージョンは シュワルツ変換イディオム に基づいています。

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: 'Pako',              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'));
15
a8m

オブジェクトの複雑な配列のソート(より多くの)

あなたはおそらくこの配列のようなもっと複雑なデータ構造に遭遇するでしょうから、私は解決策を広げるでしょう。

TL、DR

@ ege-Özcanのとても素敵な answer に基づいた、よりプラガブルなバージョンです。

問題

私は以下に遭遇しました、そしてそれを変えることができませんでした。また、オブジェクトを一時的に平らにしたくありませんでした。また、主にパフォーマンス上の理由とそれを自分で実装するための面白さのために、アンダースコアと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上

14

簡単な方法:

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

'.toLowerCase()'は文字列を比較する際のエラーを防ぐために必要であることを確認してください。

10
Caio Ladislau

Egeの動的ソリューションとVinayのアイデアを組み合わせると、Niceロバストソリューションが得られます。

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

使用法:

// 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");
9
Mike R

EgeÖzcan codeの追加の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;
    }
}
9
Behnam Yousefi

もう一つの選択肢:

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

デフォルトで昇順に並べ替えます。

9
objs.sort(function(a,b){return b.last_nom>a.last_nom})
8
Roshni Bokade

あなたの例によると、あなたは1つではなく2つのフィールド(姓、名)でソートする必要があります。 Alasql libraryを使用すると、これを1行でソートできます。

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

この例を試してください at jsFiddle

8
agershun

プロパティによってオブジェクトの配列をソートする簡単な関数

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
8
Francois Girard

混乱を防ぐために、小文字に変換する必要があります。

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

})
7
Burak Keceli

元の例を考えます。

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;
7
Bob Stein
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"));
7
Evgenii

これは単純な問題です、なぜ人々がそのような複雑な解決策を持っているのかわからない。
単純なソート機能( quick-sort algorithmに基づく):

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');
6
Gil Epshtain

Ramdaを使って、

npm install 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)
6
Sridhar Sg

xPrototype https://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"}
*/
4
Eduardo Cuomo

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

もしあなたがそれを a.a プロパティでソートしたいのであれば、私の拡張がとても役に立つと思います。このようなオブジェクトに新しい機能を追加します。

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関数を変更しました。

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

そして今、あなたは a.aでソートすることができます。 このように:

obj.sortBy('a.a');

JSFiddle の完全なスクリプトを参照してください。

4
Morteza Tourani

方法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);
4
Harunur Rashid

LodashまたはUnderscoreを使用して、そのケーキ

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

わたしにはできる。ここでは 未定義 を最後まで続けます。

 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));
    
    
3
chandan gupta

値の優先順位を変更することで、オブジェクトの配列を並べ替えることに問題が生じました。基本的に、年齢、次に姓、または単に姓、名前の順に並べ替える必要があります。私はこれが他の答えと比較して最も簡単な解決策であると思います。

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>
2
jmwierzbicki
// 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"}]"

このソースに基づいて適応: http://www.levihackwith.com/code-snippet-how-to-sort-an-array-of-json-objects-by-property/

2
Luke Schoen

これは、2レベルの入れ子になった配列を、アルファベット順に渡されたプロパティで並べ替えます。

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'));
2
depiction

したがって、ここでは、データ型の比較(つまりNumber、String)の制限なしに、あらゆる種類のオブジェクトの配列全体にわたって、任意の順序で並べ替えることができる並べ替えアルゴリズムが1つあります。

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 はブール値のパラメータで、trueの場合は昇順になり、falseの場合は降順になります。

2
Partha Roy

SelectionSortアルゴリズムを実装したソリューションを提供します。それはシンプルで効果的です。

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

そのような素晴らしい答えを見るのは素晴らしい

1
sg28

入れ子になったオブジェクトがある場合

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

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
0
Ferrybig