在javascript中对混合服装尺寸的数组进行排序

Posted

技术标签:

【中文标题】在javascript中对混合服装尺寸的数组进行排序【英文标题】:Sorting array of mixed clothing sizes in javascript 【发布时间】:2020-12-08 23:17:01 【问题描述】:

假设我有一个如下所示的数组:

$array = ['xl', 's', '1', '10', '3', 'xs', 'm', '3T', 'xxl', 'xxs', 'one size'];

我想将数组排序为如下所示:

$sortedArray = ['1', '3', '3T', '10', 'one size', 'xxs', 'xs', 's', 'm', 'xl', 'xxl'];

我怎么可能在 javascript 中对这个数组进行排序?

我可以发现一种模式,从而帮助我走上正轨,但我无法弄清楚排序功能。以数字开头的所有尺寸的模式都是第一个,按数字排序(但不确定“3T”如何处理)。然后我们显示“一个尺寸”,然后我们根据预定义的顺序对其余的(XXS、XS、S、M、L、XL、XXL)进行排序。

【问题讨论】:

数组中除了“数字或以数字开头的东西”、“一个尺寸”和正常尺寸之外,还能有更多的东西吗?就像这需要多普遍?为什么“一个尺寸”在哪里? 第一个数字(最后是 char),而不是一个大小,xxs -xxl。是这样吗? 你可以看看here,例如。 【参考方案1】:

将排序与用户定义的排序算法一起使用:我将两者都解析为与 Int 进行比较。如果其中只有一个是数字,我会比以前看到的要多。如果两者都是数字,那么我看两者是否相等。如果是这样,我从字符串中取出其余部分(它不是 Int 的一部分)并按字母顺序比较它们。否则我比较两个整数。 如果以上情况都不是真的,那么我有我的 ORDER 数组和糖果大小,我对 indexOf 进行排序。如果缺少任何内容,您可以轻松添加它们。

扩展:因为有时大小为xxlXXL,我将它们转换为小写,以便按需要进行排序。

扩展 2: 因为2XL 将被排序到数字的开头,所以我做了另一个技巧:解析为整数后,我查看字符串是否是 ORDER 数组中的一个。如果是这样,我将解析的整数设置为NaN,就像stnds一个字符串一样。通过这种方式,该条目的关键字比较发生。

扩展 3: 0 的排序是错误的,我将其添加到开头(就像 OP 的提案一样)。

array = ['XL', 's', '1', '10', '2xl', '3', '0', 'xs', 'm', '3T', 'xxl', 'xxs', 'one size'];
const ORDER = ['one size', 'xxs', 'xs', 's', 'm', 'xl', '2xl', 'xxl'];

array.sort((a,b) => 
    a = a.toLowerCase();
    b = b.toLowerCase();
    
    let nra = parseInt(a);
    let nrb = parseInt(b);
    
    if ((ORDER.indexOf(a)!=-1)) nra = NaN;
    if ((ORDER.indexOf(b)!=-1)) nrb = NaN;
  
    if (nrb===0) return 1;
    if (nra&&!nrb || nra===0) return -1;
    if (!nra&&nrb) return 1;
    if (nra && nrb) 
        if (nra==nrb) 
            return (a.substr((''+nra).length)).localeCompare((a.substr((''+nra).length)));
         else 
            return nra-nrb;
        
     else 
        return ORDER.indexOf(a) - ORDER.indexOf(b);
    
);

console.log(array);

【讨论】:

这看起来很有希望。有没有办法忽略大小写?您的小写数组排序正确,但 XL、XXL 等没有。它不应该区分大小写。 另外,如果有任何方法可以将类似 4XL 的内容添加到 ORDER 数组中,并且让原始数字排序忽略 ORDER 数组中的任何大小,那就太好了。这样一来,“4XL”之类的尺寸就会出现在最后。 我比你告诉我的要快:我在发布我的第一个解决方案后就从第二个开始,这有点棘手,第一个带有大写/小写的很容易。 谢谢,我会留意更新的答案。 我将它添加到代码中。顺便说一句,对于客户来说,如果您使用toUpperCase 并更改 ORDER-array 可能更直观,因为如果稍后添加任何内容,则使用 XXXXL 比使用 xxxl 更有可能。最好的方法是使用 const ORDER = ['xxl', ..].map(el => el.toUpperCase());,所以两者都是可能的。【参考方案2】:

你可以定义每个尺寸的weights,然后按照它排序:

let array = ['xl', 's', '1', '10', '3', 'xs', 'm', '3T', 'xxl', 'xxs', 'one size'];
let weights = 
  '1':1, 
  '3':2, 
  '3T':3, 
  '10':4, 
  'one size':5, 
  'xxs':6, 
  'xs':7, 
  's':8, 
  'm':9, 
  'xl':10, 
  'xxl':11
;
let sortedArray = array.sort((a,b)=>weights[a]-weights[b]);
console.log(sortedArray)

考虑这个问题的另一种方法是,如果两者都是数字,则通常比较值,否则依赖weights 比较:

let array = ['xl', 's', '1', '10', '3', 'xs', 'm', '3T', 'xxl', 'xxs', 'one size'];
let weights = 
  '1':1, 
  '3':2, 
  '3T':3, 
  '10':4, 
  'one size':5, 
  'xxs':6, 
  'xs':7, 
  's':8, 
  'm':9, 
  'xl':10, 
  'xxl':11
;
let sortedArray = array.sort((a,b)=>
     if(typeof(a)=="number" && typeof(b)=="number")
          return a-b;
     else
          return weights[a]-weights[b]
);
console.log(sortedArray)

【讨论】:

这绝对是最简单的方法,与真正的排序功能相比,虽然不是那么难,但比这更难。 这似乎是对的,只是听起来可以有任意数值,应该按数字排序,而不是必须在weights 中专门列出。 @Barmar 这是否意味着如果两者都是数字,则第一次比较应该在值上进行,否则在权重上进行比较? 您可能还必须先处理数字与非数字。 你可以试试这个:***.com/a/54110617/7486313。如果您使用的是npm,请查看这个库:npmjs.com/package/apparel-sorter【参考方案3】:

我会避免预定义的权重和顺序,只需设置 s = -1; m = 0; l = 1 并让前面的 xes 成为乘数。此外,将数字排在字符串之前,因为混合不同的评分系统没有意义。

function sortArrayOfGradings(array) 
    function parseGradingOrder(grading) 
        let order;
        if (grading.includes('s'))
            order = -1;
        else if (grading.includes('m'))
            order = 0;
        else if (grading.includes('l'))
            order = 1;
        const n = Number(grading.match(/\d+(?!X)/))
        const numXes = grading.match(/x*/)[0].length
        const mul = n ? n : numXes + 1
        return order * mul;
    
    return array.sort((a, b) => 
        if (!isNaN(a) && !isNaN(b))
              return a-b;
        if (!isNaN(a) && isNaN(b))
            return -1
        if (isNaN(a) && !isNaN(b))
            return 1
        if (isNaN(a) && isNaN(b)) 
            let aOrder = parseGradingOrder(a.toLowerCase());
            let bOrder = parseGradingOrder(b.toLowerCase());
            return aOrder-bOrder;
        
    );

然后您可以将任何诸如“XXXl”和“2xl”之类的东西排序在一起(不区分大小写):

sortArrayOfGradings(['xxxxl', '2xl', 'l'])
// returns ['l', '2xl', 'xxxxl']

还有:

sortArrayOfGradings(['xxxxl', '5xl', 'l'])
// returns ['l', 'xxxxl', '5xl']

但您也可以在其中输入数字:

sortArrayOfGradings([2, 2, 1, 4, 'XL', '2xl', 'xs'])
// returns [1, 2, 2, 4, 'xs', 'XL', '2xl']

【讨论】:

【参考方案4】:

简短的回答是:你不知道。

我假设您真正想要做的是能够根据它们的大小对 other 事物进行排序,其中的顺序由一些人确定(到目前为止就Javascript而言,任意)由列表指定的顺序。所以你可以这样做:编写一个排序例程,根据项目在该列表中的大小相对位置进行比较。

或者看看@MajedBadawi 的回答。

【讨论】:

在我看来,希望它按排序顺序非常有意义,例如,在下拉列表中按逻辑顺序显示它们。 这个列表的排序版本似乎也是他用来对引用它的其他事物进行排序的东西。 我认为这是实际排序和任意排序的混合。即,数字或以数字开头的事物按逻辑排序,其他所有事物都排在后面,并且是任意顺序 是吗?因为@MajedBadawi 的答案可能不够稳健,因为您不能或不想尝试对每个数字项目进行加权。对我来说,这个问题是将数组分成两组,一组可以按逻辑排序,一组任意,然后分别排序,然后将它们重新组合在一起。 @DaveNewton 我在字里行间读到了这个问题。我认为 OP 想要一些可以处理任何数字(或半数字)加上任意排序的东西,即使他们没有说得那么明确......我可能是错的

以上是关于在javascript中对混合服装尺寸的数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

在Javascript中对地址数组进行排序[重复]

如何在javascript中对嵌套的对象数组进行排序?

如何在javascript中对多维数组进行排序

在javascript中对具有偏移量的对象数组进行排序

如何在javascript中对字母数字数组进行排序[重复]

在javascript中对数组的索引进行排序