【问题标题】:sorting when keys are not present javascript using localecompare当键不存在时排序 javascript 使用 localecompare
【发布时间】:2018-03-12 23:26:07
【问题描述】:

我有下面这样的json

[
{name:'aa',age:'1Y',address:'Alaska'},
{name:'cc',age:'4Years',address:'California'},
{name:'mm',address:'Texas'}
]

每当我使用名称和地址进行排序时,它都会起作用,但如果我尝试按年龄排序,则会引发运行时错误,因为它在最后一个条目中丢失。

这是我的尝试

let obj=[
{name:'aa',age:'2y',address:'Alaska'},
{name:'cc',age:'4y',address:'California'},
{name:'bb',address:'Texas'}
]
let field='age'; //work for name and address;
let mode='string';
if(mode!='number'){
console.log (obj.sort((a, b) => a[field].toString().localeCompare(b[field].toString())));
}
else{
console.log(obj.sort((a, b) => a[field] -b[field]))
}

当键不存在时忽略条目的最佳方法是什么,我是否需要在排序之前有单独的循环来检查键。缺少钥匙的条目将在底部。

Ps:年龄从业务逻辑开始永远不会超过 10 年,它们可以以任何格式出现,例如 1,1Y,因此它被视为字符串

【问题讨论】:

  • 没有年龄的物品和有年龄的物品应该如何比较?他们应该小于吗?比...更棒?无论您想发生什么,都将其编码到您的排序回调中。
  • 编辑了问题
  • @sumit 您更改的答案将以错误的方式对年龄进行排序(nl,3 将在 25 岁之后,而 24 将在 25 岁之前),而我的答案确实对它们进行了正确排序。是否有其他理由更改已接受的答案?
  • 接受的答案在底部有缺少键的条目,在我的业务逻辑中,年龄总是小于

标签: javascript arrays sorting ecmascript-6


【解决方案1】:

只要确保你有对象的值,或者返回一个空字符串。

最短的代码路径是

(a[field] || "")

如果您指出如果a 没有该属性,它会将其视为空字符串。

不过,anull 并不能涵盖,所以如果发生这种情况,您还必须更仔细地检查它

let obj = [{
    name: 'aa',
    age: '25',
    address: 'Alaska'
  },
  {
    name: 'cc',
    age: '25',
    address: 'California'
  },
  {
    name: 'bb',
    address: 'Texas'
  }
]
let field = 'age'; //work for name and address
console.log(obj.sort((a, b) => (a[field] || "").toString().localeCompare((b[field] || "").toString())));

另一种方法是简单地比较值(再次注意,如果ab 为空,则可能存在问题)

let obj = [{
    name: 'aa',
    age: 25,
    address: 'Alaska'
  },
  {
    name: 'cc',
    age: 3,
    address: 'California'
  },
  {
    name: 'bb',
    address: 'Texas'
  }
]

function sortAndPrint( obj, field ) {
  console.log(`Sorting by ${field}`);
  console.log(obj.sort((a, b) => a[field] > b[field] ) );
}

sortAndPrint(obj, 'name');
sortAndPrint(obj, 'address');
sortAndPrint(obj, 'age');

【讨论】:

  • 这将绕过抛出的错误,但这是比较年龄的不好方法。 3 将被视为大于 20。
  • @kshetline 是的,不过对更新做了一个小小的疏忽。目前他将属性作为字符串发送,所以我不明白为什么要根据“真实”类型进行转换
  • 根据 OP,这是不行的缺少键的条目将在底部
  • @Ele 是的,你是对的,我已经用不同的方式更新了答案 ;-) 虽然在我的辩护中,当这个问题第一次被问到时还没有:)
【解决方案2】:

缺少键的条目将在底部

要求当前值来决定将要比较的内容或底部的内容。

let obj=[{name:'aa',age:'2y',address:'Alaska'},{name:'cc',age:'4y',address:'California'},{name:'bb',address:'Texas'}],
    field = 'age';
    
console.log(obj.sort((a, b) => a[field] ? b[field] ? a[field].toString().localeCompare(b[field].toString()) : -1 : 1));
.as-console-wrapper { max-height: 100% !important; top: 0; }

如果要比较此字符串10years 或此字符串5y 中的数字等,请使用正则表达式来比较数字。

let obj=[{name:'aa',age:'24y',address:'Alaska'},{name:'cc',age:'4years',address:'California'},{name:'bb',address:'Texas'}],
    field = 'age';
    
console.log(obj.sort((a, b) => {
  let evaluate = () => {
    let aval = a[field].replace(/[^\d]/g, '').trim();
    let bval = b[field].replace(/[^\d]/g, '').trim();
    
    return aval !== '' && bval !== ''  ? Number(aval) - Number(bval) : a[field].toString().localeCompare(b[field].toString());
  };
  
  return a[field] ? b[field] ? evaluate() : -1 : 1
}));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 这个答案没有正确排序数字字段,3 将在 25 之后,而 24 将在 25 之前...
  • 接受的答案在底部有缺少键的条目,在我的业务逻辑中,年龄总是小于
【解决方案3】:

let obj=[
  {name:'aa',age:'25',address:'Alaska'},
  {name:'cc',age:'25',address:'California'},
  {name:'bb',address:'Texas'}
]
let field='age'; //work for name and address
const sortFunc = (a, b) => a[field].toString().localeCompare(b[field].toString())

// If you can discard entries without the field
console.log(obj.filter(e => field in e).sort(sortFunc))

// If you cannot
console.log(obj.filter(e => field in e).sort(sortFunc).concat(obj.filter(e => !(field in e))))

【讨论】:

    【解决方案4】:

    发生这种情况是因为在最后一个元素上,当您尝试使用属性 toString 访问它时,您没有属性 age。(它是 null 与 age 键)

    【讨论】:

      【解决方案5】:

      以防万一你正在寻找一个矫枉过正的解决方案:)

        let obj=[
          {name: 'aa', age: 25, address: 'Alaska'},
          {name: 'cc', age: 24, address: 'California'},
          {name: 'mm', address: 'Texas'}
        ];
      
        let field = 'age';
        console.log (obj.sort((a, b) => {
          a = a[field];
          b = b[field];
          let defaultValue = '';
      
          if (typeof a === 'number' || typeof b === 'number') {
            defaultValue = 0;
          }
      
          a = a || defaultValue;
          b = b || defaultValue;
      
          if (typeof a === 'number') {
            return a - b;
          }
          else {
            return a.localeCompare(b);
          }
        }));
      

      这会自动处理字符串或数字,并为每个正确排序。如果您希望无年龄条目的排序高于而不是低于其他所有条目,只需将 defaultValue 为数字设置的值更改为较大的数字。

      【讨论】:

        猜你喜欢
        • 2019-03-27
        • 2020-09-20
        • 2015-10-06
        • 2020-05-14
        • 1970-01-01
        • 2015-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多