![](/img/trans.png)
[英]Sort array of objects by a given property in numbers first, then letters (with numbers having a sub-sort)
[英]How to sort array of object by properties from left to right having numbers first when property is string?
我试图先按染色体然后按 startPosition 然后按 endPosition 对这个数组进行排序这里的问题是属性是字符串类型,并且染色体包含 [1-22] 或 [x,y,m] 之间的数字
我已经根据 StackOverflow 的一些答案创建了这个函数,它的作用是比较值并以这种方式对它们进行排序,但现在的问题是它是一个字符串排序,因此它将 10 放在 2 之前
const sortByThenBy = (value, sortSettings) => {
const sortIt = () => {
const sortOrderBy = (left, right, sortOrder) => {
const sortMultiplier = sortOrder === 'asc' ? 1 : -1;
if (left > right) {
return +1 * sortMultiplier;
}
if (left < right) {
return -1 * sortMultiplier;
}
return 0;
};
return (sortLeft, sortRight) => {
const getValueByStr = (obj, path) => {
let i;
path = path.replace('[', '.');
path = path.replace(']', '');
path = path.split('.');
for (i = 0; i < path.length; i++) {
if (!obj || typeof obj !== 'object') {
return obj;
}
obj = obj[path[i]];
}
return obj;
};
return sortSettings
.map(property =>
sortOrderBy(
getValueByStr(sortLeft, property.prop),
getValueByStr(sortRight, property.prop),
property.sortOrder
)
)
.reduceRight((left, right) => right || left);
};
};
return value.sort(sortIt());
};
console.log(
sortByThenBy(item, [
{
prop: 'chromosome',
numericSort: true,
sortOrder: 'asc'
},
{
prop: 'startPosition',
sortOrder: 'asc'
},
{
prop: 'endPosition',
sortOrder: 'asc'
}
])
);
https://jsbin.com/kumavupuqi/edit?js,console,output
给定的
const item = [
{ chromosome: '2', startPosition: '980000', endPosition: '989000' },
{ chromosome: '2', startPosition: '978000', endPosition: '979000' },
{ chromosome: '1', startPosition: '978000', endPosition: '979000' },
{ chromosome: '10', startPosition: '978000', endPosition: '979000' },
{ chromosome: 'x', startPosition: '978000', endPosition: '979000' }
];
预期结果
const item = [
{ chromosome: '1', startPosition: '978000', endPosition: '979000' },
{ chromosome: '2', startPosition: '978000', endPosition: '979000' },
{ chromosome: '2', startPosition: '980000', endPosition: '989000' },
{ chromosome: '10', startPosition: '978000', endPosition: '979000' },
{ chromosome: 'x', startPosition: '978000', endPosition: '979000' }
];
在.sort
回调中,排序依据:
(1) 两个项目的染色体之间的差异是'y'
(2) 两项染色体的差为'x'
(3) 两项染色体的数值差异
(4) 两个item的startPosition的数值差
(5) 两个item的endPosition的数值差
返回第一个不为零的差值:
const arr = [ { chromosome: '2', startPosition: '980000', endPosition: '989000' }, { chromosome: '2', startPosition: '978000', endPosition: '979000' }, { chromosome: '1', startPosition: '978000', endPosition: '979000' }, { chromosome: '10', startPosition: '978000', endPosition: '979000' }, { chromosome: 'x', startPosition: '978000', endPosition: '979000' }, { chromosome: 'x', startPosition: '5', endPosition: '979000' }, { chromosome: '1', startPosition: '978000', endPosition: '9999999' }, ]; arr.sort((a, b) => ( ((a.chromosome === 'y') - (b.chromosome === 'y')) || ((a.chromosome === 'x') - (b.chromosome === 'x')) || (a.chromosome - b.chromosome) || (a.startPosition - b.startPosition) || (a.endPosition - b.endPosition) )); console.log(arr);
由于-
隐含地将双方强制为数字,这一点非常简洁。
另一种选择是创建一个函数,在给定单个对象的情况下,该函数可以得出该对象的相对值(例如,将每个染色体差异从 0 到 1e20,每个 startPosition 差异从 0 到 1e10,以及每个 endPosition 差异从 0在 1)。 然后通过该函数传递两个对象并检查它们的相对值之间的差异:
const arr = [ { chromosome: '2', startPosition: '980000', endPosition: '989000' }, { chromosome: '2', startPosition: '978000', endPosition: '979000' }, { chromosome: '1', startPosition: '978000', endPosition: '979000' }, { chromosome: '10', startPosition: '978000', endPosition: '979000' }, { chromosome: 'x', startPosition: '978000', endPosition: '979000' }, { chromosome: 'x', startPosition: '5', endPosition: '979000' }, { chromosome: '1', startPosition: '978000', endPosition: '9999999' }, ]; const getVal = (obj) => { const chr = obj.chromosome; const chromVal = chr === 'y' ? 25 : chr === 'x' ? 24 : Number(chr); return ( chromVal * 1e20 + obj.startPosition * 1e10 + Number(obj.endPosition) ); return totalVal; }; arr.sort((a, b) => getVal(a) - getVal(b)); console.log(arr);
这可能会有所帮助。
染色体坐标所需的位数各不相同。 我使用了这里的信息: https : //www.biostars.org/p/4355/来猜测POSITION_DIGITS
的合理值。
此代码使用字符串比较。 JavaScript 不能精确地表示任意大的整数。
const item = [{ chromosome: '2', startPosition: '980000', endPosition: '989000' }, { chromosome: '2', startPosition: '40', endPosition: '60' }, { chromosome: '1', startPosition: '978000', endPosition: '979000' }, { chromosome: '10', startPosition: '978000', endPosition: '979000' }, { chromosome: 'x', startPosition: '978000', endPosition: '979000' }]; const LETTERS = { x: '23', y: '24', m: '25' } const CHROMOSOME_DIGITS = 2 const POSITION_DIGITS = 10 const toStr = ({chromosome, startPosition, endPosition}) => ((LETTERS[chromosome] || chromosome.padStart(CHROMOSOME_DIGITS,'0')) + startPosition.padStart(POSITION_DIGITS,'0') + endPosition.padStart(POSITION_DIGITS,'0')) console.log(item.sort((a,b) => toStr(a).localeCompare(toStr(b))))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.