【问题标题】:sort array based on another array in javascript基于javascript中的另一个数组对数组进行排序
【发布时间】:2017-06-26 07:45:25
【问题描述】:

我有两个数组:

const originalArray = ['a', 'n', 'u', 'b', 'd', 'z'];

const sortOrder = ['n', 'z'];

所以我想输出为['n', 'z', 'a', 'u', 'b', 'd'];

基本上 originalArray 的顺序是按照 secondArray 的顺序排序的。

我可以根据第二个数组从原始数组中弹出元素,然后可以将它们附加到前面,这将为我提供所需的解决方案,但不确定这是否有效或者是否有更好的方法来使用array.sort(fxn);

const originalArray = ['a', 'n', 'u', 'b', 'd', 'z'];

const sortOrder = ['n', 'z'];
const reverseOrder = sortOrder.reverse();
for (let elem of reverseOrder) {
const indexofelem = originalArray.indexOf(elem);
 originalArray.unshift(originalArray.splice(indexofelem, 1)[0]);
}

console.log(originalArray);

【问题讨论】:

  • sortOrder 中项目的顺序 not 是否相关?为array.sort 编写一个比较函数非常简单,它只是将sortOrder 中的项目优先级放在前面;保证其他项目的稳定更复杂。
  • 是的,保持不在sortOrder中的项目的顺序是相关的。

标签: javascript arrays sorting ecmascript-6


【解决方案1】:

您可以根据sortOrder数组中的匹配索引创建排序函数。

const originalArray = ['a', 'n', 'u', 'b', 'd', 'z'];

const sortOrder = ['n', 'z'];

function sortArrays(a, b) {
  var indexOfA = sortOrder.indexOf(a),
    indexOfB = sortOrder.indexOf(b);

  if (indexOfA == -1) {
    indexOfA = sortOrder.length + 1;
  }
  if (indexOfB == -1) {
    indexOfB = sortOrder.length + 1;
  }

  if (indexOfA < indexOfB) {
    return -1;
  }

  if (indexOfA > indexOfB) {
    return 1;
  }

  return 0;
}

originalArray.sort(sortArrays);

console.log(originalArray);
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

【讨论】:

  • 如何确保原始数组中的项目保持相对位置?
【解决方案2】:

您可以使用一个对象作为项目的位置,或者采用默认值零来计算增量。

如果 delta 为零,则不会授予稳定排序。

const array = ['a', 'n', 'u', 'b', 'd', 'z'],
      sortOrder = ['n', 'z'],
      order = sortOrder.reduce((r, a, i, aa) => (r[a] = -aa.length + i, r), {});

array.sort((a, b) => (order[a] || 0) - (order[b] || 0));
console.log(array);
console.log(order);
.as-console-wrapper { max-height: 100% !important; top: 0; }

对于稳定的排序,您可以将sorting with map 与一个对象一起使用,该对象保留索引和优先级值的组。在组内,排序顺序由原始数组的索引维护。

// the array to be sorted
var list = ['a', 'n', 'u', 'b', 'd', 'z'],
    sortOrder = ['n', 'z'],
    order = sortOrder.reduce((r, a, i, aa) => (r[a] = -aa.length + i, r), {});

// temporary array holds objects with position and sort-value
var mapped = list.map(function (el, i) {
    return { index: i, group: order[el] || 0 };
});

// sorting the mapped array containing the reduced values
mapped.sort(function (a, b) {
    return a.group - b.group || a.index - b.index;
});

// container for the resulting order
var result = mapped.map(function (el) {
    return list[el.index];
});

console.log(result);

【讨论】:

  • 如何确保原始数组中的项目保持相对位置?
  • @Abhijeet,您可以使用地图和给定数组的索引进行排序,就像我对答案的编辑一样。
【解决方案3】:

对于大型数据数组处理,我们可以使用对象映射

var originalArray = ['a', 'n', 'u', 'b', 'd', 'z'],
sortOrder = ['n', 'z'];
var result = {};
var finalResponse = [];

// loop over item array which have to sort
originalArray.forEach(function(elem) {
  // if element not persent in result object then create map with true flag set
  if(!result[elem]){
    result[elem] = true
  }
});

// loop over sort order to check element exist in given array
sortOrder.forEach(function(elem) {
  //if element exist then push to array data and set flag to false for element matched.
  if(result[elem]){
    finalResponse.push(elem);
    result[elem] = false
  }
});

// loop over final object data and find all element with true value
for(var key in result) {
  if(result[key]){
   finalResponse.push(key);
  }
}
console.log('final response ',finalResponse);

【讨论】:

    【解决方案4】:

    如果您需要稳定的排序(即您希望不在 sortOrder 数组中的元素保持其原始顺序),您可以使用 Object.assign 和偏移量组合两个排序映射。

    所以,为了确保我们的排序稳定,我们结合了两个地图: - 原始索引的映射,从数据长度开始到 1 - 已定义索引的映射,按数据长度偏移

    // Create a map that holds an integer sort index for 
    // each value in an array based on its index
    const sortMap = (ref, offset = 0) => 
      ref.reduce((map, x, i) =>
        Object.assign(map, { [x]: (ref.length - i) + offset })
      , {});
    
    // Returns a function that sorts based on a value in a map
    const sortWithMap = map => (a, b) => 
      (map[b] || 0) - (map[a] || 0);
    
    
    
    const originalArray = "abcdefghijlmnopqrstuvwxyz".split("");
    const sortOrder = ['n', 'z'];
    
    
    const sortToOrder = (order, data) => data.sort(
      sortWithMap(sortMap(order))
    );
    
    
    const sortToOrderStable = (order, data) => data.sort(
      sortWithMap(Object.assign(
          sortMap(data),
          sortMap(order, data.length)
      )));
    
    console.log("Stable:",
      JSON.stringify(
        sortToOrderStable(sortOrder, originalArray)
      )
    );
    
    console.log("Default:",
      JSON.stringify(
        sortToOrder(sortOrder, originalArray)
      )
    );

    【讨论】:

    • 感谢稳定排序!!
    猜你喜欢
    • 2017-09-12
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    相关资源
    最近更新 更多