【问题标题】:Javascript sort function. Sort by First then by SecondJavascript 排序功能。按第一然后按第二排序
【发布时间】:2012-02-28 19:44:35
【问题描述】:

我有一个要排序的对象数组。每个对象都有两个参数:强度和名称

objects = []
object[0] = {strength: 3, name: "Leo"}
object[1] = {strength: 3, name: "Mike"}

我想先按强度排序,然后按名称字母顺序排序。我正在使用以下代码按第一个参数排序。我如何按秒排序?

function sortF(ob1,ob2) {
  if (ob1.strength > ob2.strength) {return 1}
  else if (ob1.strength < ob2.strength){return -1}
  return 0;
};

感谢您的帮助。

(我使用Array.sort()和前面提到的sortF作为传递给它的排序比较函数。)

【问题讨论】:

    标签: javascript arrays sorting


    【解决方案1】:

    将你的排序功能扩展成这样;

    function sortF(ob1,ob2) {
        if (ob1.strength > ob2.strength) {
            return 1;
        } else if (ob1.strength < ob2.strength) { 
            return -1;
        }
    
        // Else go to the 2nd item
        if (ob1.name < ob2.name) { 
            return -1;
        } else if (ob1.name > ob2.name) {
            return 1
        } else { // nothing to split them
            return 0;
        }
    }
    

    &lt;&gt; 字符串比较字母比较。

    【讨论】:

      【解决方案2】:

      这个小功能在多键排序时通常很方便:

      cmp = function(a, b) {
          if (a > b) return +1;
          if (a < b) return -1;
          return 0;
      }
      

      或者,更简洁地说,

      cmp = (a, b) => (a > b) - (a < b)
      

      这很有效,因为在 javascript 中:

      true - true // gives 0
      false - false // gives 0
      true - false // gives 1
      false - true // gives -1
      

      像这样应用它:

      array.sort(function(a, b) { 
          return cmp(a.strength,b.strength) || cmp(a.name,b.name)
      })
      

      Javascript 确实缺少 Ruby 的 spaceship operator,这使得这种比较非常优雅。

      【讨论】:

      • cough Perl 的宇宙飞船操作符。
      • 谢谢。一段时间以来,我一直在寻找这种知识核心……我只是不知道如何措辞。尤其是宇宙飞船操作员。
      • 喜欢这个,实现到应用程序中。这也适用于 3 个键吗?我还没到那里,但可能需要第三次排序。
      • @AndySmith: 当然,cmp(a, b) || cmp(c, d) || cmp(e, f) 等等
      • @AndyB:从那以后它就被修复了;)
      【解决方案3】:

      您可以使用逻辑 OR 链接排序顺序。

      objects.sort(function (a, b) {
          return a.strength - b.strength || a.name.localeCompare(b.name);
      });
      

      【讨论】:

      • 太棒了!但是对于强度可以未定义的情况,我们希望所有具有定义强度的对象先行。有没有像这样优雅的解决方案?
      • 可能是这样的:return ((a.strength || Number.MAX_VALUE) - (b.strength || Number.MAX_VALUE)) || a.name.localeCompare(b.name);
      • 是的,您可以为不存在的部分添加默认值,例如 return ((a.strength || Infinity) - (b.strength || Infinity)) || a.name.localeCompare(b.name);。但这取决于strength 的可能值。
      • 像魅力一样工作return a.z - b.z || a.x - b.x || a.y - b.y
      【解决方案4】:

      当我在寻找这个问题的答案时,我在 StackOverflow 上找到的答案并不是我所希望的。所以我创建了一个简单的、可重用的函数来完成这个任务。它允许您使用标准的Array.sort,但使用firstBy().thenBy().thenBy() 样式。 https://github.com/Teun/thenBy.js

      附言。这是我第二次发布这个。第一次被版主删除,说“请不要为自己的作品发宣传帖”。我不确定这里的规则是什么,但我试图回答这个问题。我很抱歉这是我自己的工作。随意再次删除,但请指出当时涉及的规则。

      【讨论】:

      • 你应该在 Readme.md 中放一个名字,姓氏的例子,因为每个人都在后面 ^^,我会试试这个库,看起来不错。
      • 是的,很好,我猜。显示真正任意的字段组合很诱人,但自述文件确实应该从最常见的照顾场景开始。感谢您的提示。
      • 这很棒。我不明白为什么版主会删除一些如此有用的东西。如果需要购买,那可能会有所不同,不过,我想这取决于我们来决定。我们都在这里长大,可以做出明智的决定。
      • 我不能为模组说话,但除了自我推销之外,我猜他们为什么要删除它:link-only answers don't contain an answer。将 40 行库源代码复制到您的答案中可能也不理想,但是复制几行代码或描述库中实现的算法将使您的答案内容独立。
      【解决方案5】:

      史蒂夫的回答,但更漂亮。

      objects.sort(function(a,b)
      {
        if(a.strength > b.strength) {return  1;}
        if(a.strength < b.strength) {return -1;}
        if(a.name     > b.name    ) {return  1;}
        if(a.name     < b.name    ) {return -1;}
        return 0;
      }
      

      【讨论】:

        【解决方案6】:
        function sortF(ob1,ob2) {
          if (ob1.strength > ob2.strength) {return 1}
          else if (ob1.strength < ob2.strength) {return -1}
          else if (ob1.name > ob2.name) {return 1}
          return -1;
        };
        

        编辑:按强度排序,然后如果强度相等,则按名称排序。 两个对象的强度和名称相等的情况不需要单独考虑,因为 -1 的最终返回表示小于或等于关系。排序的结果将是正确的。我不知道它可能使它运行得更快或更慢。如果你想明确,只需替换

        return -1;
        

        else if (ob1.name < ob2.name) {return -1}
        return 0;
        

        【讨论】:

        • 你错过了相同的情况。
        【解决方案7】:

        在下面找到“sortFn”函数。此函数按无限数量的参数排序(例如在 c# 中:SortBy(...).ThenBy(...).ThenByDesc(...))。

        function sortFn() {
            var sortByProps = Array.prototype.slice.call(arguments),
                cmpFn = function(left, right, sortOrder) {
                    var sortMultiplier = sortOrder === "asc" ? 1 : -1;
        
                    if (left > right) {
                        return +1 * sortMultiplier;
                    }
                    if (left < right) {
                        return -1 * sortMultiplier;
                    }
                    return 0;
                };
        
        
            return function(sortLeft, sortRight) {
                // get value from object by complex key
                var getValueByStr = function(obj, path) {
                    var i, len;
        
                    //prepare keys
                    path = path.replace('[', '.');
                    path = path.replace(']', '');
                    path = path.split('.');
        
                    len = path.length;
        
                    for (i = 0; i < len; i++) {
                        if (!obj || typeof obj !== 'object') {
                            return obj;
                        }
                        obj = obj[path[i]];
                    }
        
                    return obj;
                };
        
                return sortByProps.map(function(property) {
                    return cmpFn(getValueByStr(sortLeft, property.prop), getValueByStr(sortRight, property.prop), property.sortOrder);
                }).reduceRight(function(left, right) {
                    return right || left;
                });
            };
        }
        
        var arr = [{
            name: 'marry',
            LocalizedData: {
                'en-US': {
                    Value: 10000
                }
            }
        }, {
            name: 'larry',
            LocalizedData: {
                'en-US': {
                    Value: 2
                }
            }
        }, {
            name: 'marry',
            LocalizedData: {
                'en-US': {
                    Value: 100
                }
            }
        }, {
            name: 'larry',
            LocalizedData: {
                'en-US': {
                    Value: 1
                }
            }
        }];
        document.getElementsByTagName('pre')[0].innerText = JSON.stringify(arr)
        
        arr.sort(sortFn({
            prop: "name",
            sortOrder: "asc"
        }, {
            prop: "LocalizedData[en-US].Value",
            sortOrder: "desc"
        }));
        
        document.getElementsByTagName('pre')[1].innerText = JSON.stringify(arr)
        pre {
            font-family: "Courier New" Courier monospace;
            white-space: pre-wrap;
        }
        Before:
        <pre></pre>
        Result:
        <pre></pre>

        【讨论】:

        • 这个可以做一个箭头函数的版本吗?
        【解决方案8】:

        使用 ES6 你可以做到

        array.sort(function(a, b) { 
         return SortFn(a.strength,b.strength) || SortFn(a.name,b.name)
        })
        
         private sortFn(a, b): number {
            return a === b ? 0 : a < b ? -1 : 1;
        }
        

        【讨论】:

          【解决方案9】:

          这是我使用的功能。它会做一个任意的数字。

          function Sorter(){
            
            var self = this;
            this.sortDefs = [];
            
            for (let i = 0; i < arguments.length; i++) {
            // Runs 5 times, with values of step 0 through 4.
              this.sortDefs.push(arguments[i]);
            }
            
            this.sort = function(a, b){
            
              for (let i = 0; i < self.sortDefs.length; i++) {
          
                  if (a[self.sortDefs[i]] < b[self.sortDefs[i]]) { 
                    return -1;
                  } else if (a[self.sortDefs[i]] > b[self.sortDefs[i]]) {
                    return 1
                  }
              }
              
              return 0;
            }
          }
          
          data.sort(new Sorter('category','name').sort);
          

          【讨论】:

            【解决方案10】:

            在 2018 年,您可以只使用 sort() ES6 函数,它完全按照您的意愿行事。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

            【讨论】:

              猜你喜欢
              • 2016-11-07
              • 1970-01-01
              • 2016-07-19
              • 2021-05-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多