1

我正在尝试创建用于在实践中注册学生协议的Google表单。每个协议都被注册并获得格式为本年度数字的协议编号 - 今年协议的T编号/ 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不在列表首位。很快我意识到发生这种情况是因为脚本使用了字典顺序,并且“认为”2超过了10个。所以我明白,我不知何故将不得不改变这个顺序,并且做到2小于10,11小于101等等上。 我的问题是如何做到这一点?我想我需要按自然顺序排列数组元素 - 但我不知道如何做到这一点。 我尝试谷歌如何做到这一点,但结果并不令人满意 - 也许我的编码知识相当有限(我是心理学的博士生,而不是信息学):) 也许有人会帮助如何解决这个问题。

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

链接到谷歌形式(实际形式的副本):https://docs.google.com/forms/d/e/1FAIpQLSerJfkv1dgHexUwxppXNyhb46twOZgvEMOIVXSOJoED3SLmyQ/viewform

+1

你能向我们展示样品表吗?一个是最新的表格。二是你的脚本改变了一张表。这是你不想要的工作表。最后一张是你想要的一张。这些样本表将有助于那些认为解决方案的人。 – Tanaike

+0

你应该用零填充。除非您迁移它,否则太晚了。否则,你需要编写一个自定义的排序功能(如果去那条路线,向我们展示你的尝试)。自定义排序将需要了解您的确切格式,并手动比较每个部分,或填充然后只是进行比较。 16-T-3填充将是16-T-0003等 –

回答

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函数将被重复调用相同的字符串,因为它们正在排序。如果这成为一个问题(我真的不这么认为),可以通过一次转换来优化,创建一个数组数组,然后对其进行排序。

相关问题