【问题标题】:JS: Sorting array by multiple fields doesn't worksJS:按多个字段对数组进行排序不起作用
【发布时间】:2019-07-10 14:02:56
【问题描述】:

我想创建按此顺序对元素进行排序的方法:

  1. 列表中的第一个元素必须是“活动”的元素(isActive 字段设置为 true)。如果两个比较的元素都处于活动状态,则按字母顺序排序。

  2. 列表中的下一个元素是必须将字段(createSheet 和 centralBox)设置为 true 的元素。如果两个比较元素都将此字段设置为 true,则按字母顺序排序。

  3. 列表中的下一个元素是仅将 centralBox 字段设置为 true 的元素。与其他情况一样,两个元素都将这些字段设置为 true,然后按字母顺序排序。

  4. 列表中的下一个元素是仅将 createSheet 字段设置为 true 的元素。和上面一样……

  5. 层次结构中的最后一个排序是按字母排序

这是我做的,它不起作用(名称是字符串,其他文件是布尔值):

    sortingSelectList = (firstElement, secondElement) => {
    const elementToCompare = {
        name: firstElement.label.toLowerCase(),
        isActive: this.state.activeSystems.ids.includes(firstElement.label),
        createSheet: this.state.systems.entities[firstElement.label].createSheet,
        centralBox: this.state.systems.entities[firstElement.label].centralBox
    };
    const comparingElement = {
        name: secondElement.label.toLowerCase(),
        isActive: this.state.activeSystems.ids.includes(secondElement.label),
        createSheet: this.state.systems.entities[secondElement.label].createSheet,
        centralBox: this.state.systems.entities[secondElement.label].centralBox
    };

    if (elementToCompare.isActive < comparingElement.isActive) { return -1; }
    if (elementToCompare.isActive > comparingElement.isActive) { return 1; }

    if (elementToCompare.centralBox && elementToCompare.createSheet < comparingElement.centralBox && comparingElement.createSheet) { return -1; }
    if (elementToCompare.centralBox && elementToCompare.createSheet > comparingElement.centralBox && comparingElement.createSheet) { return 1; }

    if (elementToCompare.centralBox < comparingElement.centralBox) { return -1; }
    if (elementToCompare.centralBox > comparingElement.centralBox) { return 1; }

    if (elementToCompare.createSheet < comparingElement.createSheet) { return -1; }
    if (elementToCompare.createSheet > comparingElement.createSheet) { return 1; }

    if (elementToCompare.name < comparingElement.name) { return -1; }
    if (elementToCompare.name > comparingElement.name) { return 1; }

    return 0;
}

有人可以帮我吗?

示例:

Object 1: { name: B,
        isActive: true,
        createSheet: false,
        centralBox: false }
Object 2: { name: A,
        isActive: true,
        createSheet: false,
        centralBox: false }         
Object 3: { name: B,
        isActive: false,
        createSheet: false,
        centralBox: false }
Object 4: { name: B,
        isActive: false,
        createSheet: false,
        centralBox: true }
Object 5: { name: B,
        isActive: false,
        createSheet: true,
        centralBox: false }
Object 6: { name: B,
        isActive: false,
        createSheet: true,
        centralBox: true }

预期顺序:Object2 -> Object1 -> Object6 -> Object4 -> Object5 -> Object3

【问题讨论】:

标签: javascript arrays sorting


【解决方案1】:

一种方法是根据您的情况对对象进行编码和加权。看看这段代码:

var obj = [
{ name: "B",
  isActive: true,
  createSheet: false,
  centralBox: false },
{ name: "A",
  isActive: true,
  createSheet: false,
  centralBox: false },
{ name: "B",
  isActive: false,
  createSheet: false,
  centralBox: false },
{ name: "B",
  isActive: false,
  createSheet: false,
  centralBox: true },
{ name: "B",
  isActive: false,
  createSheet: true,
  centralBox: false },
{ name: "B",
  isActive: false,
  createSheet: true,
  centralBox: true }
]

for (const o of obj){
  let score = o.isActive === true ? 0 : 50
  score += o.centralBox === true ? 0 : 20
  score += o.createSheet === true ? 0 : 10
  score += o.name.charCodeAt(0)
  o.score = score
}
obj.sort((a, b) => a.score - b.score)
console.log(obj)

【讨论】:

  • 欢迎您。如果您觉得如此,请投票并将其标记为最佳答案,以帮助与您有相同问题的其他人;)
  • 如果我获得 15 个声望,我会的 :)
【解决方案2】:

比较的优先级高于&amp;&amp;,因此请尝试更改

(elementToCompare.centralBox &amp;&amp; elementToCompare.createSheet &lt; comparingElement.centralBox &amp;&amp; comparingElement.createSheet)

((elementToCompare.centralBox &amp;&amp; elementToCompare.createSheet) &lt; (comparingElement.centralBox &amp;&amp; comparingElement.createSheet))

即将要比较的内容用括号括起来。

【讨论】:

    【解决方案3】:

    您需要一个单独的对象来保存您需要的排序顺序。我过去使用过以下代码,不是我自己的,但不记得我在哪里得到它,所以不能给予信任。

    正方向表示升序排序,负方向表示相反

    let sortBy = [{
      prop:'isActive',
      direction: 1
    },{
      prop:'createSheet',
      direction: 1
    },
    {
      prop:'centralBox',
      direction: 1
    },
    {
      prop:'name',
      direction:1
    }];
    

    然后您需要遍历上面的每个属性,将每个属性应用于数组:

    array.sort(function(a,b){
      let i = 0, result = 0;
      while(i < sortBy.length && result === 0) {
        result = sortBy[i].direction*(a[ sortBy[i].prop ].toString() < b[ sortBy[i].prop ].toString() ? -1 : (a[ sortBy[i].prop ].toString() > b[ sortBy[i].prop ].toString() ? 1 : 0));
        i++;
      }
      return result;
    })
    

    ToString 转换使代码更加灵活,因此可以应用于各种排序情况。

    我们还乘以您需要的方向。

    将此应用于您的数组给出:

    【讨论】:

    • 谢谢!它有效,但我使用了 agtabesh 的解决方案,因为对于像我这样的新手来说更容易理解 :)
    【解决方案4】:

    你有很多不同的条件。 Sou 为每个条件存储过滤结果。检查filter 功能。 最后将所有数组合并到一个数组中。检查concat函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-24
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      相关资源
      最近更新 更多