使用localecompare时,按键不存在时进行排序

时间:2018-03-12 23:26:08

标签: javascript arrays sorting ecmascript-6

我喜欢下面的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,因此被视为字符串

5 个答案:

答案 0 :(得分:4)

确保您拥有该对象的值,或返回一个空字符串。

最短的代码路径是

(a[field] || "")

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

它不会涵盖a null,所以如果发生这种情况,你必须更仔细地检查它

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');

答案 1 :(得分:1)

  

缺少键的输入将位于底部

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



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; }




答案 2 :(得分:0)

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))))

答案 3 :(得分:0)

这是因为在您尝试使用属性toString访问它时,在最后一个元素上没有属性年龄。(使用年龄键为null)

答案 4 :(得分:0)

以防您正在寻找过度杀伤解决方案:)

  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);
    }
  }));

这会自动处理字符串或数字,为每个字符串或数字正确排序。如果您希望no-age条目排序更高而不是低于其他所有条目,只需将数字defaultValue设置为大数字即可。