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));
渡した値でオブジェクトをソートする動的ソート関数を作成することもできます。
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");
ES6/ES2015以降では、次のようにします。
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
アンダースコアを使用して、その小さくて素晴らしい...
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' );
人々がそれをそれほど複雑にする理由を理解しないでください:
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;
});
逆アルファベット順にソートするように演算子を交換します。
姓が重複している場合は、姓でそれらを並べ替えることができます。
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;
});
プロトタイプ継承を使用してこの問題を簡単に素早く解決する:
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"}]
更新: /元の配列を修正しません。
カスタム比較関数を使用する代わりに、カスタムの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();
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;
});
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();
ここにはたくさんの良い答えがありますが、もっと複雑なソートを実現するためにそれらを単純に拡張できることを指摘したいと思います。あなたがしなければならない唯一のことはこのような比較関数を連鎖するために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に変換できる最初の評価式 に評価される||
演算子の動作に基づいています。
最も単純な形式 には、次のようなインライン関数が1つだけあります。
// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )
last_nom
、first_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は、外部のライブラリや複雑なコードがなくても長い道のりを歩むことができるということです。文字列の解析を行う必要がないため、これも非常に効果的です。
使用例
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;
};
};
あなたが使用することができます
( 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']);
この特定のアプローチが提案されているのを見たことがないので、string
とnumber
の両方で機能する簡潔な比較方法を以下に示します。
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 > fb
はfalse
であるため、+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))
私は私のために働くコードの一部を持っています:
arr.sort((a, b) => a.name > b.name)
更新:常に動作するわけではないので、正しくありません:(
私はこの質問が古すぎることを知っていますが、私のような実装は見られませんでした。
このバージョンは シュワルツ変換イディオム に基づいています。
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'));
あなたはおそらくこの配列のようなもっと複雑なデータ構造に遭遇するでしょうから、私は解決策を広げるでしょう。
@ 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上
簡単な方法:
objs.sort(function(a,b) {
return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});
'.toLowerCase()'
は文字列を比較する際のエラーを防ぐために必要であることを確認してください。
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");
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;
}
}
もう一つの選択肢:
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>a.last_nom})
あなたの例によると、あなたは1つではなく2つのフィールド(姓、名)でソートする必要があります。 Alasql libraryを使用すると、これを1行でソートできます。
var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);
この例を試してください at jsFiddle 。
プロパティによってオブジェクトの配列をソートする簡単な関数
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
混乱を防ぐために、小文字に変換する必要があります。
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
})
元の例を考えます。
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
、a>b
の場合、-1,0,1を返します。||
は、last_nom
よりfirst_nom
の優先順位を与えます。var age_order = left.age - right.age;
return -last_nom_order || -first_nom_order || -age_order;
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"));
これは単純な問題です、なぜ人々がそのような複雑な解決策を持っているのかわからない。
単純なソート機能( 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');
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)
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"}
*/
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 の完全なスクリプトを参照してください。
方法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);
LodashまたはUnderscoreを使用して、そのケーキ
> const sortedList = _.orderBy(objs, [last_nom], [asc]); // asc or desc
わたしにはできる。ここでは 未定義 を最後まで続けます。
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));
値の優先順位を変更することで、オブジェクトの配列を並べ替えることに問題が生じました。基本的に、年齢、次に姓、または単に姓、名前の順に並べ替える必要があります。私はこれが他の答えと比較して最も簡単な解決策であると思います。
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"}]"
このソースに基づいて適応: http://www.levihackwith.com/code-snippet-how-to-sort-an-array-of-json-objects-by-property/
これは、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'));
したがって、ここでは、データ型の比較(つまり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の場合は降順になります。
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);
そのような素晴らしい答えを見るのは素晴らしい
入れ子になったオブジェクトがある場合
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"));
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