Order array of objects working for number but not string

huangapple go评论74阅读模式
英文:

Order array of objects working for number but not string

问题

我已经创建了一个实用函数来对对象数组进行升序或降序排序,该函数接受属性作为参数。它似乎可以正确对数字属性进行排序,但对字符串属性不起作用。例如,在下面的示例中,如果将"age"作为第二个参数传入,它会正确排序,但如果将"job"作为第二个参数传入,什么都不会发生。我希望它能按工作(Engineer、Marketing、Sales)的字母顺序排序。有没有办法修复这个问题或解释为什么会出现这个问题?

const arrayOfObjects = [
  { firstName: 'Joe', job: 'Engineer', age: 22 },
  { firstName: 'Sam', job: 'Sales', age: 30 },
  { firstName: 'Claire', job: 'Engineer', age: 40 },
  { firstName: 'John', job: 'Marketing', age: 29 },
  { firstName: 'Susan', job: 'Engineer', age: 21 },
];

const orderByValue = (array, orderByItem, order) => array.sort((a, b) => {
  if (order === 'descending') {
    return b[orderByItem] - a[orderByItem];
  } else {
    return a[orderByItem] - b[orderByItem];
  }
});

// console.log('order by age:', orderByValue(arrayOfObjects, 'age'));
console.log('order by job:', orderByValue(arrayOfObjects, 'job'));
英文:

I've created a util function to sort an array of objects in either ascending or descending order which accepts the property. It appears to work fine for sorting numeric, but not string properties. E.g. in the below, if you pass in "age" as the second argument it order correctly, however if you pass in "job" as the second argument, nothing happens. I was hoping it would order alphabetically by job (Engineer, Marketing, Sales). Any ideas how to fix this / why it is happening?

const arrayOfObjects = [
  { firstName: 'Joe', job: 'Engineer', age: 22 },
  { firstName: 'Sam', job: 'Sales', age: 30 },
  { firstName: 'Claire', job: 'Engineer', age: 40 },
  { firstName: 'John', job: 'Marketing', age: 29 },
  { firstName: 'Susan', job: 'Engineer', age: 21 },
];

const orderByValue = (array, orderByItem, order) => array.sort((a, b) => {
  if (order === 'descending') {
    return b[orderByItem] - a[orderByItem];
  } else {
    return a[orderByItem] - b[orderByItem];
  }
});

// console.log('order by age:', orderByValue(arrayOfObjects, 'age'));
console.log('order by job:', orderByValue(arrayOfObjects, 'job'));

答案1

得分: 4

你可以只使用 LocaleCompare,并使用 Numeric 选项来处理数字。

LocaleCompare 是一个字符串方法,所以要正确处理数字类型,你可以使用 .toString()a[orderByItem] + '',或者 String(a[orderByItem]) 来将它们转换为字符串。

const arrayOfObjects = [
  { firstName: 'Joe', job: 'Engineer', age: 22 },
  { firstName: 'Sam', job: 'Sales', age: 30 },
  { firstName: 'Claire', job: 'Engineer', age: 40 },
  { firstName: 'John', job: 'Marketing', age: 29 },
  { firstName: 'Susan', job: 'Engineer', age: 21 },
];

const orderByProperty = (array, orderByItem, order) => array.sort((a, b) => {
  if (order === 'descending') {
    return b[orderByItem].toString().localeCompare(a[orderByItem].toString(), 'en', {numeric: true});
  } else {
    return a[orderByItem].toString().localeCompare(b[orderByItem].toString(), 'en', {numeric: true});
  }
});

console.log('order by age:', orderByProperty(arrayOfObjects, 'age'));
console.log('order by job:', orderByProperty(arrayOfObjects, 'job'));
英文:

You can just use LocaleCompare, and use the Numeric option to handle the numbers as well

LocaleCompare is a String method, so to handle Number types correctly you convert them using .toString(), a[orderByItem] + '', or String(a[orderByItem])

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const arrayOfObjects = [
{ firstName: &#39;Joe&#39;, job: &#39;Engineer&#39;, age: 22 },
{ firstName: &#39;Sam&#39;, job: &#39;Sales&#39;, age: 30 },
{ firstName: &#39;Claire&#39;, job: &#39;Engineer&#39;, age: 40 },
{ firstName: &#39;John&#39;, job: &#39;Marketing&#39;, age: 29 },
{ firstName: &#39;Susan&#39;, job: &#39;Engineer&#39;, age: 21 },
];
const orderByProperty = (array, orderByItem, order) =&gt; array.sort((a, b) =&gt; {
if (order === &#39;descending&#39;) {
return b[orderByItem].toString().localeCompare(a[orderByItem].toString(), &#39;en&#39;, {numeric: true});
} else {
return a[orderByItem].toString().localeCompare(b[orderByItem].toString(), &#39;en&#39;, {numeric: true});
}
});
console.log(&#39;order by age:&#39;, orderByProperty(arrayOfObjects, &#39;age&#39;));
console.log(&#39;order by job:&#39;, orderByProperty(arrayOfObjects, &#39;job&#39;));

<!-- language: lang-css -->

.as-console-wrapper {max-height: 100% !important; top: 0;}

<!-- end snippet -->

答案2

得分: 1

你可以将一个函数作为回调返回,并在每个比较中省略对顺序的检查。这种方法仅使用大于/小于运算符,对字符串也有效。

const arrayOfObjects = [
  { firstName: 'Joe', job: 'Engineer', age: 22 },
  { firstName: 'Sam', job: 'Sales', age: 30 },
  { firstName: 'Claire', job: 'Engineer', age: 40 },
  { firstName: 'John', job: 'Marketing', age: 29 },
  { firstName: 'Susan', job: 'Engineer', age: 21 },
];

const orderByProperty = (array, orderByItem, order) => array.sort(order === 'descending'
    ? (a, b) => b[orderByItem] > a[orderByItem] || -(b[orderByItem] < a[orderByItem])
    : (a, b) => a[orderByItem] > b[orderByItem] || -(a[orderByItem] < b[orderByItem])
);

console.log('order by age:', orderByProperty(arrayOfObjects, 'age'));
console.log('order by job:', orderByProperty(arrayOfObjects, 'job'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
英文:

You could return a function as callback and omit for each comparison a check for order.

This approach uses simply greater/smaller operators, which works for strings as well.

<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const arrayOfObjects = [
{ firstName: 'Joe', job: 'Engineer', age: 22 },
{ firstName: 'Sam', job: 'Sales', age: 30 },
{ firstName: 'Claire', job: 'Engineer', age: 40 },
{ firstName: 'John', job: 'Marketing', age: 29 },
{ firstName: 'Susan', job: 'Engineer', age: 21 },
];

const orderByProperty = (array, orderByItem, order) =&gt; array.sort(order === &#39;descending&#39;
? (a, b) =&gt; b[orderByItem] &gt; a[orderByItem] || -(b[orderByItem] &lt; a[orderByItem])
: (a, b) =&gt; a[orderByItem] &gt; b[orderByItem] || -(a[orderByItem] &lt; b[orderByItem])
);
console.log(&#39;order by age:&#39;, orderByProperty(arrayOfObjects, &#39;age&#39;));
console.log(&#39;order by job:&#39;, orderByProperty(arrayOfObjects, &#39;job&#39;));

<!-- language: lang-css -->
.as-console-wrapper { max-height: 100% !important; top: 0; }
<!-- end snippet -->

huangapple
  • 本文由 发表于 2020年1月7日 00:37:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/59615781.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定