【问题标题】:Why is this sorting function returning the object in the wrong order?为什么这个排序函数以错误的顺序返回对象?
【发布时间】:2020-10-03 19:01:10
【问题描述】:

我在 CodeWars 中遇到了一个挑战,并在 runJS 中设计了一个提供我想要的结果的函数。挑战在于正确地对一组对象进行排序。我在两个三元组中使用了 .sort() 方法来完成我的任务并获得所需的结果。问题是,当我在 CW 中运行相同的函数时,它返回的输出与我在 runJS 中看到的完全不同,因此我无法通过测试。帮助?我错过了什么?为什么它会失败,为什么我在 CW 和 runJS 中看到不同的结果?

the variable and the function I am using for CodeWars

var animal = [
        { name: "Cat", numberOfLegs: 4 }, 
        { name: "Snake", numberOfLegs: 0 }, 
        { name: "Dog", numberOfLegs: 4 },
        { name: "Pig", numberOfLegs: 4 },
        { name: "Human", numberOfLegs: 2 },
        { name: "Bird", numberOfLegs: 2 }];

function sortAnimal(animal) {
  let legs = animal.sort((a, b) => a.numberOfLegs < b.numberOfLegs ? -1 : 1);
  return legs.sort((a, b) => a.name < b.name && a.numberOfLegs === b.numberOfLegs ? -1 : 1);
}

the output for this function in runJS, which is also the solution for CW

sortAnimal(animal)
// output:
[
  { name: 'Snake', numberOfLegs: 0 },
  { name: 'Bird', numberOfLegs: 2 },
  { name: 'Human', numberOfLegs: 2 },
  { name: 'Cat', numberOfLegs: 4 },
  { name: 'Dog', numberOfLegs: 4 },
  { name: 'Pig', numberOfLegs: 4 }
]

the error I receive in CodeWars

//the test:
describe("Animal sorting test", function(){
  it("", function(){
      var animal = [
        { name: "Cat", numberOfLegs: 4 }, 
        { name: "Snake", numberOfLegs: 0 }, 
        { name: "Dog", numberOfLegs: 4 },
        { name: "Pig", numberOfLegs: 4 },
        { name: "Human", numberOfLegs: 2 },
        { name: "Bird", numberOfLegs: 2 }];
     
     Test.assertSimilar( sortAnimal(animal),[{ name: 'Snake', numberOfLegs: 0 }, { name: 'Bird', numberOfLegs: 2 }, { name: 'Human', numberOfLegs: 2 }, { name: 'Cat', numberOfLegs: 4 }, { name: 'Dog', numberOfLegs: 4 }, { name: 'Pig', numberOfLegs: 4 }], "");

  });
});

Expected: '[{ name: \'Snake\', numberOfLegs: 0 }, { name: \'Bird\', numberOfLegs: 2 }, { name: \'Human\', numberOfLegs: 2 }, { name: \'Cat\', numberOfLegs: 4 }, { name: \'Dog\', numberOfLegs: 4 }, { name: \'Pig\', numberOfLegs: 4 }]', 
instead got: '[{ name: \'Cat\', numberOfLegs: 4 }, { name: \'Dog\', numberOfLegs: 4 }, { name: \'Pig\', numberOfLegs: 4 }, { name: \'Bird\', numberOfLegs: 2 }, { name: \'Human\', numberOfLegs: 2 }, { name: \'Snake\', numberOfLegs: 0 }]'

【问题讨论】:

  • 排序功能似乎工作正常,但代码战断言由于某种原因正在采用动物数组的原始值
  • CodeWars 上的 JS 在使用 Google Chrome V8 JS 引擎的 node.js 中运行。由于您的排序不正确,可能会导致不同浏览器的排序不同。
  • @ggorlen 非常感谢!虽然 runJS 说我是对的,但我还差得很远!!!
  • @Slai 谢谢!你能推荐一些类似的 javascript 'scratchpad' 我可以在上面计算函数,或者你推荐的其他一些过程来获得准确的结果吗?
  • 如果您的比较器编写正确,您将不会在不同 JS 版本的排序函数中公开实现细节(CW 在这个挑战中使用 Node 8,这已经过时了)。这个thread 可能有助于说明未考虑所有可能的比较器返回值(小于 0、0 和大于零)的无效排序如何在不同的实现中给您带来奇怪的结果。

标签: javascript


【解决方案1】:

您的排序没有考虑应该返回零的相等值。

对于数字排序,这通过使用减法来简化,减法将在相等时返回负数、正数或零。

您也没有为相等的腿数处理按字母顺序排列的名称。

首先检查腿是否相同,如果是则返回名称的字母排序,否则返回腿差异

function sortAnimal(animal) {
  return animal.sort((a,b)=>{
     if(a.numberOfLegs === b.numberOfLegs){
         // when legs are same sort by the names
         return a.name.localeCompare(b.name);
     }
     return a.numberOfLegs - b.numberOfLegs
  });  
}

const sorted = sortAnimal(animal)
console.log(JSON.stringify(sorted))

const isMatch =  sorted.every((el,i)=> Object.keys(el).every(k=> el[k] === expected[i][k]))
console.log('matches expected:', isMatch)
<script>
var animal=[{name:"Cat",numberOfLegs:4},{name:"Snake",numberOfLegs:0},{name:"Dog",numberOfLegs:4},{name:"Pig",numberOfLegs:4},{name:"Human",numberOfLegs:2},{name:"Bird",numberOfLegs:2}];
const expected=[{name:"Snake",numberOfLegs:0},{name:"Bird",numberOfLegs:2},{name:"Human",numberOfLegs:2},{name:"Cat",numberOfLegs:4},{name:"Dog",numberOfLegs:4},{name:"Pig",numberOfLegs:4}];
</script>

【讨论】:

  • @charlieftl 感谢您花时间解释。我在 runJS 中检查我的答案,但这似乎很容易产生误导性的答案。有没有你喜欢的过程或应用程序来检查你的代码,你可能会为初出茅庐的开发人员推荐任何东西?再次感谢!
  • 没关系,无论用于运行代码的环境如何,结果都应该相同。我不同意这样的评论,即只要您正确地进行排序,排序可能会有所不同,这意味着还要考虑相同的条件。对于快速便签本,我喜欢使用 repl.it
【解决方案2】:

排序条件可以与|| 运算符链接,因为比较相等应该导致falsy 0:

const animal = [ { name: "Cat",   numberOfLegs: 4 }, 
                 { name: "Snake", numberOfLegs: 0 }, 
                 { name: "Dog",   numberOfLegs: 4 }, 
                 { name: "Pig",   numberOfLegs: 4 },
                 { name: "Human", numberOfLegs: 2 }, 
                 { name: "Bird",  numberOfLegs: 2 } ]

const sortAnimal = a => a.sort((a, b) => a.numberOfLegs - b.numberOfLegs 
                                      || a.name.localeCompare(b.name))

console.log( JSON.stringify( sortAnimal(animal) ).replace(/},/g, "},\n ") )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多