【问题标题】:Sorting an array of objects values in alphabetic then numeric order按字母然后数字顺序对对象值数组进行排序
【发布时间】:2020-01-20 14:28:37
【问题描述】:

我有一个这样的对象数组:

[
  {key: "key1", label: "1"},
  {key: "key2", label: "3"},
  {key: "key3", label: "2"}, 
  {key: "key4", label: "Second"}, 
  {key: "key5", label: "First"}
] 

我想对这个数组进行排序,这样按字母顺序排列的值首先出现:

[
  {key: "key5", label: "First"},
  {key: "key4", label: "Second"}, 
  {key: "key1", label: "1"},
  {key: "key3", label: "2"}, 
  {key: "key2", label: "3"}    
] 

我想出了这个解决方案:

sortArray(list: any[], key: string) {
  return list.sort(compare);

  function compare(a, b) {
    const aIsAlphabetic = isAlphabetical(a[key]);
    const bIsAlphabetic = isAlphabetical(b[key]);

    if (aIsAlphabetic && !bIsAlphabetic) {
      return -1;
    } else if (bIsAlphabetic && !aIsAlphabetic) {
      return 1;
    }

    if (a[key] < b[key]) {
      return -1;
    }
    if (a[key] > b[key]) {
      return 1;
    }
    return 0;
  }

  function isAlphabetical(value: string) {
    return value.match(/[a-zA-Z]/i);
  }
}

该解决方案有效,但我不喜欢在sortArray 内声明多个函数的想法,我这样做对吗?或者有没有其他正确的提示?

【问题讨论】:

  • 您是否尝试仅按标签排序,然后先按字母符号排序?你可以先用字母数字划分条目,对它们进行排序,然后将其余条目添加到结果列表中。
  • 我建议防范未定义的键值。

标签: javascript arrays sorting


【解决方案1】:

这是一个相当基于意见的问题,尤其是涉及到 javascript/typescript!

简短的回答是没有正确答案。正如您所说,您的代码有效!它也干净、易读、简洁。

编写这样的嵌套函数代码的缺点是不可能单独对每个函数进行单元测试。如果您想从整体上正确测试此功能,则必须通过它抽取大量测试用例以确保其正常工作。

就我个人而言,我只是将这些嵌套函数移到高级范围内,以便我可以单独测试它们。

【讨论】:

  • 我不会单独测试。你应该测试这个功能......而不是测试它是如何做到的。该函数是black box,没有人应该关心或知道实现细节。如果以后有人重写函数以获得完全相同的最终结果,如果“私有”函数更改或被删除,测试结构可能会失败。
【解决方案2】:

您的解决方案没有任何问题。如果您可能正在编写类似的排序函数,则可以使用通用函数,传递匹配函数。

const sortArray = (arr, key, rgx, bothMatched, neitherMatched, onlyAMatched, onlyBMatched) => {
  const compare = (a, b) => {   
    const aval = a[key] || "";
    const bval = b[key] || "";
    const amatched = aval.match(rgx);
    const bmatched = bval.match(rgx);   
    if (amatched) {
      if (bmatched) {     
        return bothMatched(aval,bval);
      }    
      return onlyAMatched(a,b);
    }
    if (bmatched) {   
      return onlyBMatched(a,b)
    }     
    return neitherMatched(aval,bval);
  };  

  return arr.sort(compare);
};
 
const arr = [
  {key: "key1", label: "1"},
  {key: "key2", label: "3"},
  {key: "key3", label: "2"}, 
  {key: "key4", label: "Second"}, 
  {key: "key5", label: "First"}
] 
const key = 'label';

console.log("----- match like OP -----");
sortArray(
  arr, 
  key, 
  /[a-zA-Z]/i,
  (a,b) => a.localeCompare(b),
  (a,b) => a.localeCompare(b), 
  () => -1,
  () => 1)
.forEach(e => console.log(JSON.stringify(e)));

console.log("----- Alternative match -----");
sortArray(
  arr, 
  key, 
  /^[\d]+$/,
  (a,b) => parseInt(a,10) - parseInt(b,10), 
  (a,b) => a.localeCompare(b),
  () => 1,
  () => -1)
.forEach(e => console.log(JSON.stringify(e)));
console.log(".");

【讨论】:

    【解决方案3】:

    这应该足够了。仍然模式 'a-zA-Z' 对于其他语言是不安全的。

    let array=[{key: "key1", label: "1"}, {key: "key2", label: "3"}, {key: "key3", label: "2"}, {key: "key4", label: "Second"},{key: "key5", label: "First"}]
    let isAlphanumeric = (value:string) => (value.match(/[a-zA-Z]/i))
    
    console.log(array.sort((a, b) => a.label.localeCompare(b.label))
    .filter(obj => isAlphanumeric(obj.label))
    .concat(array.filter(obj => !isAlphanumeric(obj.label))))

    【讨论】:

      猜你喜欢
      • 2021-12-28
      • 2019-01-26
      • 2019-06-15
      • 2012-10-05
      • 2018-11-02
      • 1970-01-01
      • 2014-12-30
      • 2011-01-15
      相关资源
      最近更新 更多