【问题标题】:Sort array by order according to another array根据另一个数组按顺序对数组进行排序
【发布时间】:2014-12-04 09:05:08
【问题描述】:

我有一个从这样的数据库返回的对象:[{id:1},{id:2},{id:3}]。我有另一个数组,它指定了第一个数组的排序顺序,如下所示:[2,3,1]

我正在寻找可以接收这两个数组并返回[{id:2},{id:3},{id:1}] 的方法或算法。理想情况下,它应该是高效的,而不是 n 平方。

【问题讨论】:

    标签: javascript algorithm sorting


    【解决方案1】:

    如果你想要线性时间,首先从第一个数组构建一个哈希表,然后通过循环第二个数组来按顺序选择项目:

    data = [{id:5},{id:2},{id:9}]
    order = [9,5,2]
    
    hash = {}
    data.forEach(function(x) { hash[x.id] = x })
    
    sorted = order.map(function(x) { return hash[x] })
    
    document.write(JSON.stringify(sorted))

    【讨论】:

      【解决方案2】:

          function sortArrayByOrderArray(arr, orderArray) {
              return arr.sort(function(e1, e2) {
                  return orderArray.indexOf(e1.id) - orderArray.indexOf(e2.id);
              });
          }
      
          console.log(sortArrayByOrderArray([{id:1},{id:2},{id:3}], [2,3,1]));

      【讨论】:

        【解决方案3】:

        在您的示例中,对象最初按id 排序,这使得任务非常简单。但是,如果这不是一般情况,您仍然可以根据您的 id 值数组以线性时间对对象进行排序。

        这个想法是首先创建一个索引,将每个id 值映射到其位置,然后通过在索引中查找其id 值将每个对象插入到所需位置。这需要迭代两个长度为n 的数组,从而导致整体运行时间为O(n),或线性时间。没有渐近更快的运行时间,因为读取输入数组需要线性时间。

        function objectsSortedBy(objects, keyName, sortedKeys) {
          var n = objects.length,
              index = new Array(n);
          for (var i = 0; i < n; ++i) {  // Get the position of each sorted key.
            index[sortedKeys[i]] = i;
          }
          var sorted = new Array(n);
          for (var i = 0; i < n; ++i) {  // Look up each object key in the index.
            sorted[index[objects[i][keyName]]] = objects[i];
          }
          return sorted;
        }
        
        var objects = [{id: 'Tweety', animal: 'bird'},
                       {id: 'Mickey', animal: 'mouse'},
                       {id: 'Sylvester', animal: 'cat'}],
            sortedIds = ['Tweety', 'Mickey', 'Sylvester'];
        
        var sortedObjects = objectsSortedBy(objects, 'id', sortedIds);
        
        // Check the result.
        for (var i = 0; i < sortedObjects.length; ++i) {
          document.write('id: '+sortedObjects[i].id+', animal: '+sortedObjects[i].animal+'<br />');
        }

        【讨论】:

          【解决方案4】:

          据我了解,排序不是必需的;至少在您的示例中,可以在线性时间内生成所需的结果数组,如下所示。

          var Result;
          for ( var i = 0; i < Input.length; i++ )
          {
              Result[i] = Input[Order[i]-1];
          }
          

          这里Result 是所需的输出,Input 是您的第一个数组,Order 是包含所需位置的数组。

          【讨论】:

          • 这假定原始数组已经按id 值排序并且它们是连续的。
          • 你是对的,但是提供的示例同时具有这两个属性,并且在其他地方没有不同地说明它们可能被违反。
          【解决方案5】:
          var objArray = [{id:1},{id:2},{id:3}];
          var sortOrder = [2,3,1];
          
          var newObjArray = [];
          for (i in sortOrder) {
              newObjArray.push(objArray[(sortOrder[i]) - 1])
          };
          

          【讨论】:

          • obj 数组不能被 sortorder 索引
          • 我的错误。我认为问题是第二个数组有排序的位置,而不是 id 值。
          【解决方案6】:

          为什么不直接创建新数组并将第二个数组中的值推入?如果我错了,请纠正我

          array1 = [];
          array2 = [2,3,1];
          
          for ( var i = 0; i < array2 .length; i++ )
          {
              array1.push({
                   id : array2[i]
               })
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-11-10
            • 1970-01-01
            • 2019-08-04
            • 2020-07-03
            • 1970-01-01
            • 2013-12-24
            • 2021-08-12
            • 2015-06-08
            相关资源
            最近更新 更多