0

在 JavaScript 中,我有一个对象数组和一个输入值,如下所示:

const inputVal = 'foo';

const objArray = [
    {title: 'blahaa', type: 'foobar'},
    {title: 'foobar', type: 'wohoo'},
    {title: 'foobar', type: 'foobar'},
    {title: 'foobar', type: 'aaaabaa'},
    {title: 'foobar', type: 'moo'},
    {title: 'aaah', type: 'foogoo'},
    {title: 'foohiii', type: 'foobar'},
    {title: 'aaah', type: 'foobar'},
    {title: 'foodoo', type: 'aaaabaa'},
    {title: 'gaaaaaah', type: 'foobar'},
    {title: 'foobar', type: 'foogoo'},
];

如您所见,数组中的所有元素在标题或类型中都有以“foo”开头的属性。此外,所有元素都是唯一的,相同的标题和/或类型可以在多个元素中,但两者的相同组合不能出现两次。

我想按以下方式对该数组进行排序:

  1. 标题和类型都以inputVal
    1. 按字母顺序输入
    2. 标题按字母顺序
  2. 标题以inputVal但不是类型 开头
    1. 按字母顺序输入
    2. 标题按字母顺序
  3. 类型以inputVal但不是标题 开头
    1. 按字母顺序输入
    2. 标题按字母顺序

示例列表将按以下方式排序:

const objArray = [
    {title: 'foobar', type: 'foobar'}, // Criterium 1
    {title: 'foohiii', type: 'foobar'}, // Criterium 1
    {title: 'foobar', type: 'foogoo'}, // Criterium 1
    {title: 'foobar', type: 'aaaabaa'}, // Criterium 2
    {title: 'foodoo', type: 'aaaabaa'}, // Criterium 2
    {title: 'foobar', type: 'moo'}, // Criterium 2
    {title: 'foobar', type: 'wohoo'}, // Criterium 2
    {title: 'aaah', type: 'foobar'}, // Criterium 3
    {title: 'blahaa', type: 'foobar'}, // Criterium 3
    {title: 'gaaaaaah', type: 'foobar'}, // Criterium 3
    {title: 'aaah', type: 'foogoo'}, // Criterium 3
];

我尝试使用array.prototype.sort(callback)几种不同的回调函数,但似乎没有得到正确的回调函数。谁能帮我?

4

3 回答 3

3

您可以连接标准并首先按三组排序,然后按值排序。

const
    value = 'foo',
    start = (v => s => s.startsWith(v))(value),
    array = [{ title: 'blahaa', type: 'foobar' }, { title: 'foobar', type: 'wohoo' }, { title: 'foobar', type: 'foobar' }, { title: 'foobar', type: 'aaaabaa' }, { title: 'foobar', type: 'moo' }, { title: 'aaah', type: 'foogoo' }, { title: 'foohiii', type: 'foobar' }, { title: 'aaah', type: 'foobar' }, { title: 'foodoo', type: 'aaaabaa' }, { title: 'gaaaaaah', type: 'foobar' }, { title: 'foobar', type: 'foogoo' }];
    
array.sort((a, b) =>
       (start(b.title) && start(b.type)) - (start(a.title) && start(a.title))
    || start(b.title) - start(a.title)
    || start(b.type) - start(a.type)
    || a.type.localeCompare(b.type)
    || a.title.localeCompare(b.title)
);

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

于 2019-08-14T12:14:13.203 回答
0

这是另一种解决方案,由于使用了多个正则表达式,可能效率较低。

const objArray = [
    {title: 'blahaa', type: 'foobar'},
    {title: 'foobar', type: 'wohoo'},
    {title: 'foobar', type: 'foobar'},
    {title: 'foobar', type: 'aaaabaa'},
    {title: 'foobar', type: 'moo'},
    {title: 'aaah', type: 'foogoo'},
    {title: 'foohiii', type: 'foobar'},
    {title: 'aaah', type: 'foobar'},
    {title: 'foodoo', type: 'aaaabaa'},
    {title: 'gaaaaaah', type: 'foobar'},
    {title: 'foobar', type: 'foogoo'}
];

const input = "foo";

const sortedObjArray = [
    objArray.sort((a, b) => {
        const
            regex = new RegExp("^(" + input + ")?(.*)", "i"),
            titleAExec = regex.exec(a.title),
            typeAExec = regex.exec(a.type),
            titleBExec = regex.exec(b.title),
            typeBExec = regex.exec(b.type)

        const
            titleComparison = titleAExec[2].localeCompare(titleBExec[2]),
            typeComparison = typeAExec[2].localeCompare(typeBExec[2])

        if (titleAExec[1] && !titleBExec[1])
            return -1
        else if (titleBExec[1] && !titleAExec[1])
            return 1

        if (typeAExec[1] && !typeBExec[1])
            return -1
        else if (typeBExec[1] && !typeAExec[1])
            return 1

        if (typeComparison === 0)
            return titleComparison

        return typeComparison;
    })
]

console.log(sortedObjArray)

于 2019-08-14T12:42:47.080 回答
-1

您可以尝试以下方法:

  1. 使用 Array.prototype.filter 根据上面提到的 3 个标准将数组拆分为 3 个子数组。
  2. 独立排序 3 个子数组,然后使用 Array.prototype.concat 连接

为了提高性能,异步处理所有子数组。分而治之获胜!

于 2019-08-14T12:10:09.953 回答