如何使用 lodash 的 _sortBy() 按自定义要求按字母顺序排序此列表?

How to use lodash's _sortBy() to alphabetically sort this list with a custom requirement?

我有以下对象数组:

const myList = [
  { id: 1, title: '[A] Animal Bite - F - Not Pregnant' },
  { id: 2, title: '[P] Sinus Pain - M' },
  { id: 3, title: '[A] Animal Bite - F - Pregnant' },
  { id: 4, title: 'Check up male' },
  { id: 5, title: '[A] Animal Bite - M' },
  { id: 6, title: 'Duration' },
  { id: 7, title: '[P] Skin Injury - F - Not Pregnant' },
  { id: 8, title: '[P] Skin Injury - M' },
  { id: 9, title: 'Emergency Screening' }
]

完成后:

_.sortBy(myList, 'title');

我得到:

Check up male
Duration
Emergency Screening
[A] Animal Bite - F - Not Pregnant
[A] Animal Bite - F - Pregnant
[A] Animal Bite - M
[P] Sinus Pain - M
[P] Skin Injury - F - Not Pregnant
[P] Skin Injury - M

看起来不错,只是我希望没有 [A] 或 [P] 的项目位于底部而不是顶部。所以像这样:

[A] Animal Bite - F - Not Pregnant
[A] Animal Bite - F - Pregnant
[A] Animal Bite - M
[P] Sinus Pain - M
[P] Skin Injury - F - Not Pregnant
[P] Skin Injury - M
Check up male
Duration
Emergency Screening

如何实现?

这是使用函数 Array.prototype.sort()

的替代方法

假设字符串中最多有一个[

const myList = [  { id: 1, title: '[A] Animal Bite - F - Not Pregnant' },  { id: 2, title: '[P] Sinus Pain - M' },  { id: 3, title: '[A] Animal Bite - F - Pregnant' },  { id: 4, title: 'Check up male' },  { id: 5, title: '[A] Animal Bite - M' },  { id: 6, title: 'Duration' },  { id: 7, title: '[P] Skin Injury - F - Not Pregnant' },  { id: 8, title: '[P] Skin Injury - M' },  { id: 9, title: 'Emergency Screening' }];

myList.sort((a, b) => {
  if (a.title.startsWith("[") && b.title.startsWith("[")) {
    return a.title.substring(1).localeCompare(b.title.substring(1)); 
  } 
  
  return a.title.localeCompare(b.title);
});

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

在排序函数中使用 localeComparenumeric: false 选项:

const list = [ { id: 1, title: '[A] Animal Bite - F - Not Pregnant' }, { id: 2, title: '[P] Sinus Pain - M' }, { id: 3, title: '[A] Animal Bite - F - Pregnant' }, { id: 4, title: 'Check up male' }, { id: 5, title: '[A] Animal Bite - M' }, { id: 6, title: 'Duration' }, { id: 7, title: '[P] Skin Injury - F - Not Pregnant' }, { id: 8, title: '[P] Skin Injury - M' }, { id: 9, title: 'Emergency Screening' } ] 

const r = list.sort((a,b) => a.title.localeCompare(b.title, 0, {numeric: false}))

console.log(r)

您也可以获得相同结果的另一种方法是通过 {caseFirst: lower'} 选项参数,如 @xehpuk asnwer 所述(并解释):

const list = [ { id: 1, title: '[A] Animal Bite - F - Not Pregnant' }, { id: 2, title: '[P] Sinus Pain - M' }, { id: 3, title: '[A] Animal Bite - F - Pregnant' }, { id: 4, title: 'Check up male' }, { id: 5, title: '[A] Animal Bite - M' }, { id: 6, title: 'Duration' }, { id: 7, title: '[P] Skin Injury - F - Not Pregnant' }, { id: 8, title: '[P] Skin Injury - M' }, { id: 9, title: 'Emergency Screening' } ] 

const r = list.sort((a,b) => a.title.localeCompare(b.title, 0, {caseFirst: 'lower'}))

console.log(r)

如果 ES6 是一个选项,您也不需要 lodash。

lodash 的 sortBy 可能会采用比较器列表。所以你可以声明 "words don't start from square bracket go later" 并在 "group" 中按标题排序

_.sortBy(myList, [
    item => !item.title.startsWith("["), 
    'title'
]);

并且使用 orderBy 您甚至可以以更具可读性(和灵活)的方式指定顺序:

_.orderBy(myList, [
    item => item.title.startsWith("["), 
    'title'
], ['desc', 'asc']);

[UPD] @Ele 提到的 startsWith 看起来更好

如果你真的想用lodash,可以对比一下lower-case中的标题:

_.sortBy(myList, item => item.title.toLowerCase());

这是有效的,因为 lower-case 个字符的代码单元 (97 - 122) 大于 [ 个字符 (91) 的代码单元。这也有利于比较标题 case-insensitively.

您可以通过检查字符串将括号部分移到顶部,然后取本地比较结果。

const
    startsWithBrackets = s => /^\[.+\]/.test(s),
    myList = [{ id: 1, title: '[A] Animal Bite - F - Not Pregnant' }, { id: 2, title: '[P] Sinus Pain - M' }, { id: 3, title: '[A] Animal Bite - F - Pregnant' }, { id: 4, title: 'Check up male' }, { id: 5, title: '[A] Animal Bite - M' }, { id: 6, title: 'Duration' }, { id: 7, title: '[P] Skin Injury - F - Not Pregnant' }, { id: 8, title: '[P] Skin Injury - M' }, { id: 9, title: 'Emergency Screening' }];

myList.sort(({ title: a }, { title: b }) =>
    startsWithBrackets(b) - startsWithBrackets(a) || a.localeCompare(b));

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