当属性是字符串时,如何按属性从左到右排序对象数组,首先具有数字?
Posted
技术标签:
【中文标题】当属性是字符串时,如何按属性从左到右排序对象数组,首先具有数字?【英文标题】:How to sort array of object by properties from left to right having numbers first when property is string? 【发布时间】:2020-05-09 04:38:18 【问题描述】:我试图先按染色体然后按 startPosition 然后按 endPosition 对这个数组进行排序 这里的问题是属性是字符串类型,染色体包含 [1-22] 或 [x,y,m] 之间的数字
我已经根据一些 *** 答案创建了这个函数,它的作用是比较值并以这种方式对它们进行排序,但现在的问题是它是一个字符串排序,所以它将 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'
];
【问题讨论】:
position
整数值的最大值是多少?
@Ben 它在 1-22 或 X,Y,M 之间的任意位置表示染色体值,其他字段未知最大值。但我的目标是创建可以采用设置 obj 并在此基础上进行排序的函数,就像我在示例中所做的那样
【参考方案1】:
在.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);
-
隐含地将双方强制转换为数字,这一事实非常简洁。
另一种选择是创建一个函数,给定单个对象,该函数可以得出该对象的相对值(例如,在 1e20 处从 0 开始计算每个染色体差异,在 1e10 处从 0 开始计算每个 startPosition 差异,以及每个 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);
【讨论】:
我最终使用了第一个解决方案,到目前为止似乎有效,但我不知道“-”【参考方案2】:这可能会有所帮助。
染色体坐标所需的位数各不相同。我使用来自这里的信息: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))))
【讨论】:
感谢您的回答和染色体的网站。我最终使用了CertainPerformance 第一个解决方案,但您的解决方案也有效。以上是关于当属性是字符串时,如何按属性从左到右排序对象数组,首先具有数字?的主要内容,如果未能解决你的问题,请参考以下文章