尝试将数组按数字排序,然后再按字母排序

4

我正在尝试对一个数组进行排序,需要按照"itemCommodity"进行排序。我需要先按照数字进行排序,然后再将有字母的数字排在最后。例如:

1000 A120 B330 2020 J954 5000

应该显示为:

1000 2020 5000 A120 B330 J954

我希望有人能帮我解决这个问题。我下面有一个示例,但它并没有按照我的预期工作。

var product_data = [{
"itemCommodity": "1000",
},
{
"itemCommodity": "B330",
},
{
"itemCommodity": "A120",
},
{
"itemCommodity": "J954",
},
{
"itemCommodity": "5000",
},
{
"itemCommodity": "2020",
}]

 product_data.sort(function(a, b) {
     return a.itemCommodity - b.itemCommodity;
 });

请注意,itemCommodity不是数组中唯一的对象。我有大约40个不同的对象,只是试图对itemCommodity进行排序。
9个回答

7

首先将不包含任何字母的元素进行排序。然后,比较它们的第一个字符来对其余元素进行排序。

var product_data = [{a:"1000"},{a:"B330"},{a:"A120"},{a:"J954"},{a:"5000"},{a:"2020"}],
    x = product_data.sort(function(a, b) {
      return /[A-Za-z]/.test(a.a) - /[A-Za-z]/.test(b.a) || a.a.charCodeAt(0) - b.a.charCodeAt(0)
    });

    console.log(x);

如果您同时拥有小写和大写字母,您需要将它们全部转换为一个共同的大小写,然后进行排序:

var product_data = [{a:"1000"},{a:"B330"},{a:"a120"},{a:"J954"},{a:"5000"},{a:"2020"}],
    x = product_data.sort(function(a, b) {
      return /[A-Za-z]/.test(a.a) - /[A-Za-z]/.test(b.a) || (a.a.toUpperCase() < b.a.toUpperCase() ? -1 : a.a.toUpperCase() > b.a.toUpperCase() ? 1 : 0)
    });

    console.log(x);


1
这太神奇了,它是如何工作的?.test() 不是返回一个布尔值吗? - Jonathan Portorreal
5
起初我认为:“有些人遇到问题时,会想‘我知道了,我会使用正则表达式。’这样他们就会有两个问题。”但是对于抽象一些、字母不在前面的情况,这是解决问题的方法。点赞+1。 - Craicerjack
@Craicerjack 谢谢,非常感激。 - kind user
作为对未来的开发人员的提示(因为它看起来很奇怪),@JonathanPortorreal,由于“-”是一个算术运算符,在执行“true - false”时,js将布尔值强制转换为数字(与“null +''”会给出null字符串的方式相同),因此它将翻译成“1-0”。 - Kieran Osgood

5

你可以这样尝试将它们进行比较

product_data.sort(function(a, b) {
     return a.itemCommodity > b.itemCommodity;
});

如果你想要字母的顺序排序,可以尝试以下方法:

 product_data.sort(function(a, b) {
     return a.itemCommodity.toLowerCase() > b.itemCommodity.toLowerCase();
});

1
我原以为这个解决方案很好,甚至比我的更好,但我错了。它只在字母位于字符串的第一个位置时才有效。如果它在中间或末尾 - 它不能正常工作。 - kind user

3

根据ASCII表,数字排在字母前面,因此您可以直接使用sort()方法对它们进行排序,如下所示:

["1000","A120","B330","2020", "J954", "5000"].sort()

结果

["1000", "2020", "5000", "A120", "B330", "J954"]

然而,在你的示例中没有直接给出数组,因此你可以遍历JSON的所有节点并直接比较它们。

"1000" > "A120" => false; "1000" < "A120" => true 

所以你的代码只需要做一点小改动:

    var product_data = [{
    "itemCommodity": "1000",
    },
    {
    "itemCommodity": "B330",
    },
    {
    "itemCommodity": "A120",
    },
    {
    "itemCommodity": "J954",
    },
    {
    "itemCommodity": "5000",
    },
    {
    "itemCommodity": "2020",
    }]
    
     product_data.sort(function(a, b) {
         return a.itemCommodity > b.itemCommodity;
     });
    
    console.log(product_data);


"1000" > "A120" => false; "1000" < "A120" => true"1000" 大于 "A120" => 错误;"1000" 小于 "A120" => 正确 - Amit Kumar Gupta
1
@AmitGupta 这不是对所提出问题的回答。实际上,这根本不是一个答案。用户有一个对象数组,他想按属性排序。 - Craicerjack
1
它不能正常工作。只有当字母在字符串的第一个位置时才能正常工作。如果它在中间或末尾,它就不能正常工作。 - kind user
1
尝试使用["100a0","A120","B330","2020", "J954", "5000"]。即使第一个元素中有字母'a',它仍将位于第一位。 - kind user
让我们在聊天中继续这个讨论 - Amit Kumar Gupta
显示剩余5条评论

2

这不是数组中唯一的对象,我大约还有40个或更多。itemCommodity只是其中之一。 - Tom
1
这不是一个关联数组。它是一个对象数组。 - Craicerjack

2
您可以使用localeCompare()方法来对数据进行排序。 参考文献

var product_data = [
  {
    itemCommodity: '1000',
  },
  {
    itemCommodity: 'B330',
  },
  {
    itemCommodity: 'A120',
  },
  {
    itemCommodity: 'J954',
  },
  {
    itemCommodity: '5000',
  },
  {
    itemCommodity: '2020',
  },
];

var sorted_data = product_data.sort(function (a, b) {
  return a.itemCommodity.localeCompare(b.itemCommodity, undefined, {
    numeric: true,
  });
});

console.log(sorted_data);


1

我认为这就是你所寻找的内容。它有点冗长,但可以完成任务。假设您不知道对象的键是什么,这将基于其值对对象进行排序,而无需先前了解键。首先按升序排序数字,然后按升序排序字符串。您可以通过更改compare函数的返回和数字的sort函数的返回来更改此顺序。

var numbersAlphAscending = (a, b) => {
  // get unknown keys
  var currentKeyA = Object.keys(a)[0];
  var currentKeyB = Object.keys(b)[0];
  
  // if item is a number
  if (Number(a[currentKeyA]) && Number(b.itemCommodity)) {
    return a[currentKeyA] - b[currentKeyB];
  }

  // if item is a string
  if (!Number(a[currentKeyA]) && !Number(b[currentKeyB])) {
    return a[currentKeyA].toLowerCase() > b[currentKeyB].toLowerCase();
  }

  // numbers before strings
  return Number(a[currentKeyA]) ? -1 : 1;

}

var product_data = [{"itemCommodity": "1000",},{"itemCommodity": "B330",},{"itemCommodity": "A120",},{"itemCommodity": "J954",},{"itemCommodity": "5000",},{"itemCommodity": "2020",}]

console.log(product_data.sort(numbersAlphAscending));


那并不是按顺序排序。它们需要按数字和字母顺序排列。 - Tom

1
你可以使用 map 创建一个数组,并使用 sort 进行排序。

      var numArray = [];
    var product_data = [{
    "itemCommodity": "1000",
    },
    {
    "itemCommodity": "B330",
    },
    {
    "itemCommodity": "A120",
    },
    {
    "itemCommodity": "J954",
    },
    {
    "itemCommodity": "5000",
    },
    {
    "itemCommodity": "2020",
    }]


     product_data.map(function(value, index) {
       numArray.push(value["itemCommodity"]); 
    })

        numArray.sort();
        var newNum=(numArray.join(","));
        alert(newNum);


他没有一个字符串数组,而是一个对象数组。 - Craicerjack
@Craicerjack,我已经解决了这个问题。希望您现在能够正确地找到它。 - Hemant
OP希望对product_data进行排序,因此您需要重新创建一个对象数组,并按新的排序顺序进行排序,以使其成为完整的解决方案。@匿名 - Jonathan Portorreal
它不能正常工作。只有当字母在字符串的第一个位置时才能正常工作。如果它在中间或末尾,它就不能正常工作。 - kind user

1
  1. 将数组缩减为两个数组- 一个没有字母,另一个有字母
  2. 对每个数组的顺序进行排序
  3. 最后,将两个排序后的数组连接在一起

var product_data = [
 { "itemCommodity": "1000" },
 { "itemCommodity": "B330" },
 { "itemCommodity": "A120" },
 { "itemCommodity": "J954" },
 { "itemCommodity": "5000" },
 { "itemCommodity": "2020" }
];

product_data
  // We reduce into two array - one without letters, another with letters
  .reduce((arr, record) => {
    const index = (record.itemCommodity.match(/[a-z]/i)) ? 1 : 0;
    arr[index].push(record);
    return arr;
  }, [[],[]])
  // We sort the two array respectively
  .map((arr) => arr.sort((a,b) => a.itemCommodity > b.itemCommodity))
  // We concat the two sorted array
  .reduce((curr, next) => curr.concat(next));

console.log(product_data);


0

如果两个值都是非数字的,你可以尝试使用基于字符串的比较小技巧,否则请使用数字排序。

var product_data = [{
    "itemCommodity": "1000",
   },
   {
   "itemCommodity": "B330",
   },
   {
   "itemCommodity": "A120",
   },
   {
   "itemCommodity": "J954",
   },
   {
   "itemCommodity": "5000",
   },
   {
   "itemCommodity": "2020",
   }
];

product_data.sort(function(a, b) {
    if(isNaN(a) || isNaN(b))
        return a.itemCommodity.toLowerCase() > b.itemCommodity.toLowerCase();
    else
       return +a.itemCommodity.toLowerCase() > +b.itemCommodity.toLowerCase();
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接