如何使用混合(字母和数字)元素按自然顺序对数组元素进行排序

时间:2017-01-23 22:09:47

标签: javascript arrays sorting google-apps-script google-sheets

我正在尝试创建google表单,用于注册学生的练习协议。每份协议均已注册并获得协议编号,格式为当前年度的数字 - 今年的协议数量/ M。例如现在它是17-T-11 / M.协议数量目前由负责实践的人员编写。 以下是以下脚本代码:

function onChange(e) 
{
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
  var range = sheet.getDataRange();
  var values = range.getValues();
  var comboValues = ['16-T-105/M']; 

   // removing titles from 0 column and 1 line (titles)
  for (var i = 1; i <= values.length; i++) {
    var v = values[i] && values[i][0];
    v && comboValues.push(v)
  }

  // Sort the values
  comboValues.sort(
    function(a, b) {
      if (b.toLowerCase() < a.toLowerCase()) return -1;
      if (b.toLowerCase() > a.toLowerCase()) return 1;
      return 0;
    }
  );
  Logger.log(comboValues);

  // google-form modification
  var form = FormApp.openById('1SHgVIosoE34m9cny9EQySljvgnRpzffdFEZe-kzNOzA');

  var items = form.getItems();
  for (i = 4; i < items.length; i++) {
    Logger.log("ID: " + items[i].getId(), ': ' + items[i].getType());
  }

  form.getItemById('2087613006').asListItem().setChoiceValues(comboValues);

我遇到了与词典顺序有关的问题。登记协议的人从名单最后登记的协议编号选择:试图做最后登记的协议编号总是在名单上。当我开始这一切的时候一切都很好(它从16-T-105 / M号开始),但新的一年到来,很快在17-T-10 / M协议登记后我得到了问题,即17-T-10 / M不在列表顶部。很快我就意识到这是因为脚本使用了词典顺序而且#34;认为&#34;那个2大于10.所以我明白我不得不改变那个顺序,并且2小于10,11小于101,依此类推。 我的问题是如何做到这一点?我想我需要按自然顺序排序数组元素 - 但我不知道如何做到这一点。 我试着谷歌如何做到这一点,但结果并不令人满意 - 也许我的编码知识非常有限(我是心理学博士生,而不是信息学):) 也许有人会帮助解决这个问题。

更新: 链接到电子表格:https://docs.google.com/spreadsheets/d/1FH5qYTrLUNI2SCrcaqlwgu8lzAylaTkZsiALg0zIpCM/edit#gid=1620956794

链接到Google表单(实际表单的副本):https://docs.google.com/forms/d/e/1FAIpQLSerJfkv1dgHexUwxppXNyhb46twOZgvEMOIVXSOJoED3SLmyQ/viewform

1 个答案:

答案 0 :(得分:1)

您应该调整排序方法以考虑数据的特殊性。这是一种方法:函数splitConvert处理每个字符串,用非单词字符拆分,然后转换可以转换为整数的字符串(并小写其余字符串)。然后比较一个接一个地通过这个数组。

comboValues.sort(
  function(a, b) {
    var as = splitConvert(a);
    var bs = splitConvert(b);
    for (var i = 0; i < as.length; i++) {
      if (bs[i] < as[i]) return -1;
      if (bs[i] > as[i]) return 1;
    }
    return 0;
  }
);

function splitConvert(str) {
  return str.split(/\W/).map(function(part) {
    var x = parseInt(part, 10);
    return isNaN(x) ? part.toLowerCase() : x;
  });
}

这不是面向性能最强的解决方案:split-parse函数将在对它们进行排序时在相同的字符串上重复调用。如果这成为一个问题(我真的不这么认为),可以通过一次转换,创建一个数组,然后对其进行排序来优化。

相关问题