【问题标题】:Why is my array sort out of order?为什么我的数组排序不正确?
【发布时间】:2018-08-24 23:57:14
【问题描述】:

我正在尝试执行以下操作。

首先,输入一个字符串并计算唯一单词的数量。
其次,对唯一字数进行降序排序。
第三,如果两个单词的字数相同,则按出现的顺序排列。

问题:为什么“up”这个词首先出现在我返回的数组中?

var doc = 
"Cause I'm Slim Shady, yes I'm the real Shady, All you other Slim Shadys are just imitating So won't the real Slim Shady, please stand up, Please stand up, Please stand up";

function wordCountEngine(doc) {
    var stringModArr = doc.replace(/[.,'\/#!$%\^&\*;:{}=\-_`~?()]/g, "").toLowerCase().split(" ");
    var wordLibrary = {};

    for (let i = 0; i < stringModArr.length; i++) {
        if (wordLibrary.hasOwnProperty(stringModArr[i])) {
            wordLibrary[stringModArr[i]] = String((Number(wordLibrary[stringModArr[i]])) + 1);
        } else {
            wordLibrary[stringModArr[i]] = '1';
        }
    }

    var sortable = [];
    for (var word in wordLibrary) {
        sortable.push([word, wordLibrary[word]]);
    }

    var final = sortable.sort(function(a, b) {
        return b[1] - a[1];
    });

    return final;
}

wordCountEngine(doc)

【问题讨论】:

    标签: javascript arrays sorting


    【解决方案1】:

    用于排序功能的排序算法不能保证原始顺序。如果将日志放在 compareFunction 中,则可以对其进行调试。如果需要订单,那么您必须在编写代码时考虑到这一点。下面的代码可能会有所帮助。

    var 文档 = “因为我是Slim Shady,是的,我是真正的Shady,所有其他Slim Shady都在模仿所以真正的Slim Shady不会,请站起来,请站起来,请站起来”;

       function wordCountEngine(doc) {
         var stringModArr = doc.replace(/[.,'\/#!$%\^&\*;:{}=\-_`~?()]/g, 
          "").toLowerCase().split(" ");
    var wordLibrary = {};
    
    for (let i = 0; i < stringModArr.length; i++) {
        if (wordLibrary.hasOwnProperty(stringModArr[i])) {
            wordLibrary[stringModArr[i]] = String((Number(wordLibrary[stringModArr[i]])) + 1);
        } else {
            wordLibrary[stringModArr[i]] = '1';
        }
    }
    
    var sortable = [];
    let i = 0;
    for (var word in wordLibrary) {
        sortable.push([i, word, wordLibrary[word]]);
        i++;
    }
    var final = sortable.sort(function(a, b) {
        if(b[2] - a[2] != 0) {
          return b[2] - a[2];
        } else {
          return a[0] - b[0];
        }
    });
    
    return final.map(a => [a[1], a[2]]);
      }
    
      wordCountEngine(doc)
    

    【讨论】:

      【解决方案2】:

      “up”首先显示,因为您的函数是根据“count”降序排序的。

      > wordCountEngine(doc)
      [ [ 'up', '3' ],
        [ 'slim', '3' ],
        [ 'shady', '3' ],
        [ 'please', '3' ],
        [ 'stand', '3' ],
        [ 'the', '2' ],
        [ 'real', '2' ],
        [ 'im', '2' ],
        [ 'you', '1' ],
        [ 'cause', '1' ],
        [ 'shadys', '1' ],
        [ 'are', '1' ],
        [ 'just', '1' ],
        [ 'imitating', '1' ],
        [ 'so', '1' ],
        [ 'wont', '1' ],
        [ 'yes', '1' ],
        [ 'all', '1' ],
        [ 'other', '1' ] ]
      

      如果您想按单词的字母顺序排序,请在调用sort 时使用 0 索引而不是 1。

      【讨论】:

      • 它应该按计数排序。但是,当两个单词具有相同的计数时,它应该排序,其次是按出现的顺序。所以“slim”、“shady”、“please”、“stand”都是3(就像“up”是3)并且都是有序的。但是“up”应该在“stand”之后(参见 doc 变量中的短语)。
      • 你传递给sort的函数需要返回一个整数。如果b[1] - a[1] 为零,也许你想执行额外的逻辑?
      【解决方案3】:

      你按顺序推送它们,但是当你对它们进行排序时,出现的顺序就丢失了。

      为了取回它,您需要根据出现次数来衡量它们的数量。这可以通过切片创建一个新数组来使用,然后在比较中考虑它们之前的顺序。

      var final = sortable.slice().sort(function(a, b) {
        var occurenceWeightA = (sortable.length - sortable.indexOf(a)) / sortable.length;
        var occurenceWeightB = (sortable.length - sortable.indexOf(b)) / sortable.length;
        return (occurenceWeightB + (+b[1])) - (occurenceWeightA + (+a[1]));
      });
      

      jsFiddle Demo

      (+b[1]) 的使用是为了确保使用整数数学而不是字符串连接。 + 是转换为数字的简写。

      【讨论】:

        【解决方案4】:

        这是一种稍微不同的方法,它向您的 wordLibrary 添加值作为您的单词键的值,该对象跟踪 firstIndexlastIndex 在句子中出现的单词以及之前的计数。

        这使您可以更好地跟踪和稍后进行排序,并且您现在可以使用元数据:

        var doc =
          "Cause I'm Slim Shady, yes I'm the real Shady, All you other Slim Shadys are just imitating So won't the real Slim Shady, please stand up, Please stand up, Please stand up";
        
        function wordCountEngine(doc) {
          var stringModArr = doc.replace(/[.,'\/#!$%\^&\*;:{}=\-_`~?()]/g, "").toLowerCase().split(" ");
          var wordLibrary = {};
        
          for (let i = 0; i < stringModArr.length; i++) {
            var key = stringModArr[i],
              obj = {first: stringModArr.indexOf(key),last: stringModArr.lastIndexOf(key)}
              wordLibrary[key] = Object.assign(obj, { count: wordLibrary[key] ? Number(wordLibrary[key].count || 1) + 1 : 1 })
          }
        
          var sortable = [];
          for (var word in wordLibrary) {
            sortable.push([word, wordLibrary[word]]);
          }
        
          var final = sortable.sort(function(a, b) {
            return b[1].count - a[1].count === 0 ? a[1].first - b[1].first : b[1].count - a[1].count
          });
        
          return final;
        }
        
        console.log(wordCountEngine(doc))

        所以它的工作方式是,如果您的单词具有相同的计数,您现在可以将它们与它们的第一次出现等进行比较。

        你可以把它缩短很多,但我想保留大部分结构,这样你就可以有宾至如归的感觉:)。希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-31
          相关资源
          最近更新 更多