【问题标题】:How to natural-sort a collection of objects in JavaScript?如何在 JavaScript 中对对象集合进行自然排序?
【发布时间】:2020-02-06 11:00:00
【问题描述】:

Belong 是我的对象集合的一个示例。

const a = [
    {name: "John", size: "100"},
    {name: "John", size: "80"},
    {name: "John", size: "82"},
    {name: "John", size: "110"},
    {name: "John", size: "70"},
    {name: "John", size: "M"},
    {name: "John", size: "S"},
    {name: "John", size: "XS"},
    {name: "John", size: "L"},
    {name: "John", size: "XL"},
]

如何在 JavaScript 中以自然的方式对 100 大于 80 以及 100 位于 80 之后的示例进行排序?

挑战在于 size 的值是数字和字符串的混合。

升序的期望结果:

[
    {name: "John", size: "70"},
    {name: "John", size: "80"},
    {name: "John", size: "82"},
    {name: "John", size: "100"},
    {name: "John", size: "110"},
    {name: "John", size: "L"},
    {name: "John", size: "M"},
    {name: "John", size: "S"},
    {name: "John", size: "XL"},
    {name: "John", size: "XS"},
]

降序的期望结果:

[
    {name: "John", size: "XS"},
    {name: "John", size: "XL"},
    {name: "John", size: "S"},
    {name: "John", size: "M"},
    {name: "John", size: "L"},
    {name: "John", size: "110"},
    {name: "John", size: "100"},
    {name: "John", size: "82"},
    {name: "John", size: "80"},
    {name: "John", size: "70"},
]

我已经按升序尝试了 Lodash JavaScript 库,但它没有正确排序,因为它看到 100 小于 80,因为 1001 开头。

_.orderBy(a, ["size"], ["asc"])

【问题讨论】:

    标签: javascript sorting sql-order-by lodash natural-sort


    【解决方案1】:

    因为您已经在使用 loadsh。只需编写一个函数来评估 size 是 String 还是 Integer,然后它会为您排序。

    对于 desc,你可以只反转 asc 数组。

    const a = [ {name: "John", size: "100"}, {name: "John", size: "80"}, {name: "John", size: "82"}, {name: "John", size: "110"}, {name: "John", size: "70"}, {name: "John", size: "M"},    {name: "John", size: "S"}, {name: "John", size: "XS"}, {name: "John", size: "L"}, {name: "John", size: "XL"} ];
    
    // ascednding
    const b = _.orderBy(a, function(e) { return isNaN(e.size) ? e.size: parseInt(e.size)}, ["asc"]);
    console.log("ASCENDING::");
    console.log(b);
    
    //descending
    const c = _.reverse(b);
    console.log("DESCENDING::");
    console.log(c);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

    【讨论】:

    • 您的解决方案效果很好。但就我而言,我的页面上有数千条记录,我使用 Vue.js 及其反应性功能来更新表格。然后它不能正确排序。有什么线索吗?
    【解决方案2】:

    升序和降序

    const arr = [{name: "John", size: "100"},{name: "John", size: "80"},{name: "John", size: "82"},{name: "John", size: "110"},{name: "John", size: "70"},{name: "John", size: "M"},{name: "John", size: "S"},{name: "John", size: "XS"},{name: "John", size: "L"},{name: "John", size: "XL"}],
          handler = (a, b, desc) => {
            if (isNaN(+a) && isNaN(+b)) return (desc ? b.localeCompare(a) : a.localeCompare(b));
            else if (!isNaN(+a) && !isNaN(+b)) return (desc ? (+b - +a) : (+a - +b));
            else if (isNaN(+a)) return (desc ? -1 : 1); 
            else return (desc ? 1 : -1);
          },
          descending = arr.sort(({size: a}, {size: b}) => handler(a, b, true)),
          ascending = [...arr].sort(({size: a}, {size: b}) => handler(a, b));
    
    console.log("Ascending")
    console.log(ascending);
    console.log("Descending")
    console.log(descending);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 您的解决方案适用于我的一页上有数千条记录的情况。我如何对多个属性进行排序,例如名称和大小?
    【解决方案3】:
      let array_data = [
        {name: "John", size: "70"},
        {name: "John", size: "80"},
        {name: "John", size: "82"},
        {name: "John", size: "100"},
        {name: "John", size: "110"},
        {name: "John", size: "L"},
        {name: "John", size: "M"},
        {name: "John", size: "S"},
        {name: "John", size: "XL"},
        {name: "John", size: "XS"},
    ];
    
        let  sorted = array_data.sort((a, b) => {return parseInt(a.size) - parseInt(b.size);});
        console.log(sorted);
    

    正常的排序javascript函数将起作用。

    【讨论】:

      【解决方案4】:

      const a = [
      		{name: "John", size: "100"},
      		{name: "John", size: "80"},
      		{name: "John", size: "82"},
      		{name: "John", size: "110"},
      		{name: "John", size: "70"},
      		{name: "John", size: "M"},
      		{name: "John", size: "S"},
      		{name: "John", size: "XS"},
      		{name: "John", size: "L"},
      		{name: "John", size: "XL"},
      	]
      // ascending
      const sorted = arr => [...arr].sort((a, b) => a.size.localeCompare(b.size, 'en', {numeric: true}))
      console.log(sorted(a))

      【讨论】:

        【解决方案5】:

        您可以使用普通的 JavaScript 逻辑来实现这一点。您可以显式创建尺寸映射,以帮助您根据要求对值进行排序:

        const a = [
            {name: "John", size: "100"},
            {name: "John", size: "80"},
            {name: "John", size: "82"},
            {name: "John", size: "110"},
            {name: "John", size: "70"},
            {name: "John", size: "M"},
            {name: "John", size: "S"},
            {name: "John", size: "XS"},
            {name: "John", size: "L"},
            {name: "John", size: "XL"},
        ];
        var sizes = {
          '100': 3,
          '80': 1,
          '82': 2,
          '110': 4,
          '70': 0,
          'M': 6,
          'S': 7,
          'XS': 9,
          'L': 5,
          'XL': 8,
        }
        //ascending
        a.sort((x, y) => {
          return sizes[x.size] - sizes[y.size];
        });
        
        console.log(a);
        
        //descending
        a.sort((x, y) => {
          return sizes[y.size] - sizes[x.size];
        });
        
        console.log(a);

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-10
          • 2015-04-23
          • 2010-11-15
          • 1970-01-01
          • 2017-09-27
          相关资源
          最近更新 更多