使数组唯一

时间:2018-07-01 16:48:14

标签: google-apps-script google-sheets

我正在尝试使列中以竖线分隔的单元格值唯一

示例

如果D3的单元格值= Aa Bb | HH | Aa Bb | HH

然后在运行arrMakeUnique_n()之后,D3的单元格值= Aa Bb | HH

这是可行的,但是如果D2的单元格值与D3相同,则仅使D3的单元格值唯一D2不变

如果有多个具有相同值的单元格,则只有一个单元格是唯一的,其他单元格保持不变

我不明白为什么,需要任何帮助

谢谢

function arrMakeUnique_n() {

 arrMakeUnique(
  'sheet1',
  ["Header"], 
  "|",
  "|"
  );
}

function arrMakeUnique(shtName,cheaders, dilm1, dilm2) {
  var sheet = SpreadsheetApp.getActive().getSheetByName(shtName);
  var range = sheet.getDataRange();
  var rangeValues = range.getValues();
  var LR = sheet.getLastRow();

  var hn =[];
  var fhn = [];
  for (var k = 0; k <= cheaders.length-1; k++) { 
       //Get column indexes from headers
       hn[k] = HTN(shtName,cheaders[k]) - 1; 
  } 

  for (var j = 0; j <= cheaders.length-1; j++) {
    var frRange = sheet.getRange(2, hn[j]+1, LR-1, 1); 
    var frValues = frRange.getValues(); 

    // iterate through all cells in the selected range
   for (var cellRow = 1; cellRow < LR; cellRow++) {

        //Make array with split on | get unique with .getUnique() then Join with |
        //Logger.log((rangeValues[cellRow][hn[j]].toString().split(frValues[cellRow]+dilm1)).getUnique().join(frValues[cellRow]+dilm2).trim())
        rangeValues[cellRow][hn[j]] = (rangeValues[cellRow][hn[j]].toString().split(frValues[cellRow]+dilm1)).getUnique().join(frValues[cellRow]+dilm2).trim();       
    }
  } 
  // Write back all values at once
  range.setValues(rangeValues); 
}

编辑:事实证明,使用:.getUnique会导致奇怪的行为,因为它干扰了其他与使用无关的脚本。 xyz解决方案非常幸运

//Make array unique
Array.prototype.getUnique = function(){
   var u = {}, a = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(u.hasOwnProperty(this[i])) {
         continue;
      }
      a.push(this[i]);
      u[this[i]] = 1;
   }
   return a;
}


function HTN(shtName,cheader){
  var headers = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(shtName).getDataRange().getValues().shift();
  var colindex = headers.indexOf(cheader);
  return colindex+1;
}

4 个答案:

答案 0 :(得分:3)

您真的需要编写脚本吗?以下使用本机函数的公式可以正常工作。

=join("|", unique(transpose(split(D3, "|", false, true))))

也许插入列,向下运行该公式然后将结果还原为值并删除原始列(无论是否使用脚本)会更容易。

enter image description here

答案 1 :(得分:3)

使用数组合并功能(对于其他用例,您也会发现它非常有用):

function deDupe(){
  var spread = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spread.getActiveSheet();
  sheet.getRange("D3").setValue(merge(sheet.getRange("D3").getValue().split("|")));
  //In your scenario only D3 is modified, but I think you forgot to ask, if D3 and D2 are different AFTER the code runs, then set them equal.
  if (sheet.getRange("D3").getValue()!=sheet.getRange("D2").getValue()){
    sheet.getRange("D2").setValue(sheet.getRange("D3").getValue());
    //Or do something different
  }
}


function merge(a1, a2) {
  var hash = {};
  var arr = [];
  var target = "";
  for (var i = 0; i < a1.length; i++) {
    if (hash[a1[i]] !== true) {
      target = a1[i].trim();
      if (target.length>0) {
        hash[target] = true;
        arr[arr.length] = target;
      }
    }
  }
  if (arguments.length == 2) {
    for (var i = 0; i < a2.length; i++) {
      if (hash[a2[i]] !== true) {
        target = a2[i].trim();
        if (target.length>0) {
          hash[target] = true;
          arr[arr.length] = target;
        }
      }
    }
  }
  return arr;
}

请注意,我只传递了一个要合并的数组。如果您两次传递相同的数组,它实际上的工作原理相同,但是显然会花费更多时间。

答案 2 :(得分:3)

更改此

rangeValues[cellRow][hn[j]] = (rangeValues[cellRow][hn[j]].toString().split(frValues[cellRow]+dilm1)).getUnique().join(frValues[cellRow]+dilm2).trim();

对此

rangeValues[cellRow][hn[j]] = rangeValues[cellRow][hn[j]].toString().split(dilm1).getUnique().join(dilm2).trim();

此外,如果您要对单元格值进行排序

//Make array unique
Array.prototype.getUnique = function(){
   var u = {}, arr = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(u.hasOwnProperty(this[i])) {
         continue;
      }
      arr.push(this[i]);
      u[this[i]] = 1;
   }

  arr.sort(lowerCase);
  function lowerCase(a,b){
    return a.toLowerCase()>b.toLowerCase() ? 1 : -1;// sort function that does not "see" letter case
  }
   return arr;
}

答案 3 :(得分:2)

这是另一种方法:

function removeDuplicateFromDilmStr_n() {
var t="Abb Baa|HHH|Abb Baa"
Logger.log(removeDuplicateFromDilmStr(t,"|", "|"))
}

function removeDuplicateFromDilmStr(str, dilm1, dilm2){
var arr = str.toString().split(dilm1)
var outArray = [];

arr.sort(lowerCase);
function lowerCase(a,b){
return a.toLowerCase()>b.toLowerCase() ? 1 : -1;// sort function that does not "see" letter case
}
var unique_array = arr.filter(function(elem, index, self) {
    return index == self.indexOf(elem);
});

unique_array = unique_array.join(dilm2).trim();

return unique_array
}

然后更改此:

rangeValues[cellRow][hn[j]] = (rangeValues[cellRow][hn[j]].toString().split(frValues[cellRow]+dilm1)).getUnique().join(frValues[cellRow]+dilm2).trim();

对此:

rangeValues[cellRow][hn[j]] = removeDuplicateFromDilmStr(rangeValues[cellRow][hn[j]], "|","|");