【问题标题】:JavaScript: Sorting array accorting to "outside" parameterJavaScript:根据“外部”参数对数组进行排序
【发布时间】:2019-08-14 11:31:39
【问题描述】:

在 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) 与几个不同的回调函数一起使用,但我似乎没有得到正确的回调函数。谁能帮帮我?

【问题讨论】:

  • 如果foo 不包含在任何地方会发生什么?
  • 请显示您现有的回调函数
  • 您检查过哪些不同的回调?
  • 请将您的尝试添加到问题中。您是否尝试过使用startsWith
  • 为什么aaah 低于gaaaaah?在原始顺序中,两者的顺序不同,并且没有规则切换它们。

标签: javascript arrays sorting


【解决方案1】:

您可以连接条件并首先按三个组排序,然后按值排序。

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

【讨论】:

    【解决方案2】:

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

    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)

    【讨论】:

      【解决方案3】:

      您可以尝试以下方法:

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

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

      【讨论】:

      • 过滤器在这里不起作用,过滤器删除元素,而是排序。您已经概括了问题并且没有提供明确的解决方案。异步性与这个问题无关。尝试创建一个实际可行的可运行解决方案,并备份它为什么会起作用,而不是仅仅陈述它。
      • 通过拆分我的意思是这样做 -> jsfiddle.net/y1wL7dsq 现在每个数组可以在执行 concat 之前按字母顺序异步排序。
      • 那你为什么不在这里做一个sn-p,表明你的意思?
      • 它成功了,但是你可以把代码放到这里的 sn-p 中。
      • 我仍然不明白为什么我的回答被否决了。我假设 OP 已经熟悉按字母顺序排序,并且只提供了所需的主要逻辑。
      猜你喜欢
      • 2011-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-30
      • 1970-01-01
      • 2020-04-21
      • 2018-12-27
      • 2018-08-16
      相关资源
      最近更新 更多