Вот немного измененная версия элегантной реализации из книги «JavaScript: Хорошие детали».
ПРИМЕЧАНИЕ. Эта версия by
является стабильной. Он сохраняет порядок первого сорта, выполняя следующий цепной сортировку.
Я добавил к нему параметр isAscending
. Кроме того, он был преобразован в ES6
стандарты и «новые» хорошие части, как рекомендовано автором.
Вы можете сортировать как по возрастанию, так и по убыванию и сортировать по нескольким свойствам.
const by = function (name, minor, isAscending=true) {
const reverseMutliplier = isAscending ? 1 : -1;
return function (o, p) {
let a, b;
let result;
if (o && p && typeof o === "object" && typeof p === "object") {
a = o[name];
b = p[name];
if (a === b) {
return typeof minor === 'function' ? minor(o, p) : 0;
}
if (typeof a === typeof b) {
result = a < b ? -1 : 1;
} else {
result = typeof a < typeof b ? -1 : 1;
}
return result * reverseMutliplier;
} else {
throw {
name: "Error",
message: "Expected an object when sorting by " + name
};
}
};
};
let s = [
{first: 'Joe', last: 'Besser'},
{first: 'Moe', last: 'Howard'},
{first: 'Joe', last: 'DeRita'},
{first: 'Shemp', last: 'Howard'},
{first: 'Larry', last: 'Fine'},
{first: 'Curly', last: 'Howard'}
];
// Sort by: first ascending, last ascending
s.sort(by("first", by("last")));
console.log("Sort by: first ascending, last ascending: ", s); // "[
// {"first":"Curly","last":"Howard"},
// {"first":"Joe","last":"Besser"}, <======
// {"first":"Joe","last":"DeRita"}, <======
// {"first":"Larry","last":"Fine"},
// {"first":"Moe","last":"Howard"},
// {"first":"Shemp","last":"Howard"}
// ]
// Sort by: first ascending, last descending
s.sort(by("first", by("last", 0, false)));
console.log("sort by: first ascending, last descending: ", s); // "[
// {"first":"Curly","last":"Howard"},
// {"first":"Joe","last":"DeRita"}, <========
// {"first":"Joe","last":"Besser"}, <========
// {"first":"Larry","last":"Fine"},
// {"first":"Moe","last":"Howard"},
// {"first":"Shemp","last":"Howard"}
// ]
Проще говоря, вы не можете использовать типы массивов «alias».
Вы можете обойти это, инкапсулируя вещи в struct
, но это не отвечает на ваш вопрос.
Обновление:
Из стандарта ECMA
using-alias-директива:
blockquote>
using
идентификатор = namespace-type-name-name ;, который явно ничего не говорит о разрешенных массивах.
(см. стр. 100 о том, как определено имя имя пространства имен или имя .)
Я бы просто получил свой тип из System.Array. Если я правильно интерпретирую то, что вы описываете, это не-OO-подход, как вы бы использовали в plain C.
Update. Думаю, вы не можете подклассы System.Array. Возможно, вокруг есть способ.
using ResourceMessageParamsType = System.Array;
Не то, чтобы я притворялся, что понимаю, как этот «код [сериализации] защиты от возможных изменений в определении класса» для вас.
Интерфейсы были бы более чистым подходом, и вы рассматривали дженерики ?
Всеобъемлющие модульные тесты IMO гарантируют, что если кто-то изменит тип псевдонимов, все код десериализации будет работать.
Вы можете определить класс (или структуру), называемый ResourceMessageParamsType, и определить неявные операторы для каста в объект и из объекта [].
struct ResourceMessageParamsType
{
private object[] value;
private ResourceMessageParamsType(object[] value)
{
this.value = value;
}
public static implicit operator object[](ResourceMessageParamsType t)
{
return t.value;
}
public static implicit operator ResourceMessageParamsType(object[] value)
{
return new ResourceMessageParamsType(value);
}
}