繁体   English   中英

当属性是字符串时,如何从左到右按属性对对象数组进行排序,首先是数字?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM