Сделать массив уникальным - PullRequest
0 голосов
/ 01 июля 2018

Я пытаюсь сделать значения ячеек с разделителями в столбце уникальными

Пример

если значение ячейки D3 = Aa Bb | ЧЧ | Aa Bb | ЧЧ

затем после запуска arrMakeUnique_n () значение ячейки D3 = Aa Bb | ЧЧ

И это работает, но если значение ячейки D2 совпадает с D3, то только значение ячейки D3 становится уникальным. D2 не изменяется

1011 * т.е. *

Если имеется несколько ячеек с одинаковым значением, только одна ячейка становится уникальной, остальные остаются без изменений

Не могу понять почему, любая помощь ценится

Спасибо

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 голосов
/ 02 июля 2018

Вот еще один метод:

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]], "|","|");
0 голосов
/ 02 июля 2018

Используйте функцию слияния массивов (вы также найдете это очень полезным для других случаев использования):

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;
}

Обратите внимание, что я передаю только один массив для слияния. На самом деле он работает одинаково, если вы передаете один и тот же массив дважды, но, очевидно, это займет больше времени.

0 голосов
/ 02 июля 2018

Изменить это

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;
}
0 голосов
/ 01 июля 2018

Вы действительно должны написать это? Следующая формула с использованием встроенных работает нормально.

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

Возможно, было бы проще вставить столбец, запустить эту формулу, а затем вернуть результаты в значения и удалить исходный столбец (в сценарии или нет).

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...