Google apps script 从一列中收集所有唯一值并在另一列中输出。。?

Google apps script 从一列中收集所有唯一值并在另一列中输出。。?,google-apps-script,google-sheets,output,unique-values,Google Apps Script,Google Sheets,Output,Unique Values,我有这种形式的电子表格: A B C D abc abc abc 1 def ghi jkl 1 mno pqr stu 3 vwx yza bcd 4 mno pqr stu 5 mno pqr stu 5 vwx yza bcd 5 mno pqr stu 1 其中前3列只是字符串类型的数据。列D有整数,其中的数字重复。我的问题是如何输出这样的第五列: A B C D E abc abc abc 1 1 def ghi jkl 1 3 mno pqr stu 3 4

我有这种形式的电子表格:

 A   B   C  D
abc abc abc 1
def ghi jkl 1
mno pqr stu 3
vwx yza bcd 4
mno pqr stu 5
mno pqr stu 5
vwx yza bcd 5
mno pqr stu 1
其中前3列只是字符串类型的数据。列D有整数,其中的数字重复。我的问题是如何输出这样的第五列:

 A   B   C  D E
abc abc abc 1 1
def ghi jkl 1 3
mno pqr stu 3 4
vwx yza bcd 4 5
mno pqr stu 5
mno pqr stu 5
vwx yza bcd 5
mno pqr stu 1
它只输出D列中的唯一数字

我设想在for或while循环中运行if/else语句,检查“D”中的每个单元格,并在数组中存储以前未“看到”的任何值。然后输出列E中的数组

我想知道是否有更有效的方法来做到这一点。以上只是一个小例子。数据范围很可能在400范围内。(按行。包括新的输出列在内,列数仅为4或5。)

提前谢谢

附言。
我在这里搜索了这个,但我只得到了与删除重复行相关的问题。如果有问题已经提出了,请将我链接到它。

这里有一种方法可以做到这一点。。。可能不是唯一的一个,但可能不坏

我添加了一些日志,以便在记录器中查看中间结果

function keepUnique(){
  var col = 3 ; // choose the column you want to use as data source (0 indexed, it works at array level)
  var sh = SpreadsheetApp.getActiveSheet();
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var data=ss.getDataRange().getValues();// get all data
  Logger.log(data);
  var newdata = new Array();
  for(nn in data){
    var duplicate = false;
    for(j in newdata){
      if(data[nn][col] == newdata[j][0]){
        duplicate = true;
      }
    }
    if(!duplicate){
      newdata.push([data[nn][col]]);
    }
  }
  Logger.log(newdata);
  newdata.sort(function(x,y){
  var xp = Number(x[0]);// ensure you get numbers
  var yp = Number(y[0]);
  return xp == yp ? 0 : xp < yp ? -1 : 1;// sort on numeric ascending
});
  Logger.log(newdata);
 sh.getRange(1,5,newdata.length,newdata[0].length).setValues(newdata);// paste new values sorted in column of your choice (here column 5, indexed from 1, we are on a sheet))
  }

给出了完全相同的结果

您可以在谷歌电子表格中使用
独特的
功能来实现这一点。
.
(您可以在
过滤器
类别中找到
唯一

您最有可能希望插入单元格
E1

=UNIQUE(D1:D)
这将使用所有列
D
中的唯一值填充列
E
,同时保留顺序。此外,这将动态更新并反映对列
D
所做的所有更改

要从谷歌应用程序脚本中执行此操作,请执行以下操作:

SpreadsheetApp.getActiveSheet()
 .getRange("E1").setFormula("=UNIQUE(D1:D)");

下面是一个脚本,用于获取列中非空值的唯一列表,给定它所在的工作表和列的标题位置,使用数组存储值,使用indexOf查找重复项。然后,您可以在任何需要的地方编写数组

headerLocation是一个位置对象:

var Location = function(sheet, row, col) {
  this.sheet = sheet;
  this.row = row;
  this.col = col;
  this.addRow = function() { this.row = this.row + 1; }
  this.addCol = function() { this.col = this.col + 1; }
  this.getValue = function() { return sheet.getRange(this.row, this.col).getValue(); }
  this.toString = function() { return "(" + this.row + "," + this.col + ")"; }
}
此函数用于读取列并返回唯一值:

/**
* Get unique values in column, assuming data starts after header
* @param {Sheet} sheet - Sheet with column to search
* @param {object} headerLocation - row and column numbers of the column header cell
* @returns {array} list of unique values in column
*/
function getUniqueColumnValues(sheet, headerLocation) {
  let startRow = headerLocation.row + 1;
  let lastRow = sheet.getLastRow();
  let values = [];
  for (i = startRow ; i <= lastRow ; i++) {
    let value = sheet.getRange(i, headerLocation.col).getValue();
    if ((value != "") && (values.indexOf(value) == -1)) {
      values.push(value);
    }
  }  
  return values;
}
/**
*获取列中的唯一值,假设数据在标头之后开始
*@param{Sheet}Sheet-包含要搜索的列的工作表
*@param{object}headerLocation-列标题单元格的行和列编号
*@返回列中唯一值的{array}列表
*/
函数getUniqueColumnValues(表格、标题位置){
设startRow=headerLocation.row+1;
设lastRow=sheet.getLastRow();
让值=[];

对于(i=startRow;i目前,在V8发动机中,最简单的方法是使用:

/**
*@returns{Object[]}获取二维数组中的唯一值
*@param{Object[]]}array2d
*@私人
*/
const getUnique_u2;=array2d=>[…新集合(array2d.flat())];
/**
*从列中获取值,使其唯一并设置修改后的值
*转到下一列
*@param{string}sheetName
*@param{number}要uniquify的列的列号
*@param{number}头数头数
*@返回无效
*/
const uniquifyAColumn=(sheetName='Sheet1',column=3,headers=1)=>{
const sh=SpreadsheetApp.getActive().getSheetByName(sheetName),
rg=sh.getRange(1+标题,列,sh.getLastRow()-标题,1),
values=rg.getValues(),
uniqueValues=getUnique(values).map(e=>[e]);
rg.偏移量(0,1,uniqueValues.length).setValues(uniqueValues);
};

再次感谢。这段代码也运行得非常完美和快速。一个问题是“for循环”的语法是什么?(数据中的
nn
部分)。我一直认为您必须这样做:
(nn=0;nn这只是一个简短的形式,通常它包括这样的var声明:
for(数据中的var nn){…
但是“正常的方式也差不多,在这种情况下,
应该是(var nn=0;nn我很高兴,很乐意帮忙。:-)看看同一主题;-)是的,在你让我感兴趣之后,我就开始了一场关于这个主题的研究狂潮。我从来都不知道即使是一个简单的“for”循环也会有这么多的复杂性。嗯……那似乎太简单了!谢谢!我打赌上面的Serge代码就是这个
独特的
函数的最终根源。有没有办法使用公式要在脚本中返回值而不是在电子表格中设置值?我有一个用例,我只需要脚本中的数据,不需要将其放入工作表中。@GreatWitnoth如果您找到问题的答案,您刚才问我们是否可以将返回值存储到数组中,请帮我一个忙,然后将其发布到omewhere。这会帮我很大的忙。谢谢!!使用map效果很好,但我会在获取范围之前检查起始行和要搜索的行是否有效。
/**
* Get unique values in column, assuming data starts after header
* @param {Sheet} sheet - Sheet with column to search
* @param {object} headerLocation - row and column numbers of the column header cell
* @returns {array} list of unique values in column
*/
function getUniqueColumnValues(sheet, headerLocation) {
  let startRow = headerLocation.row + 1;
  let lastRow = sheet.getLastRow();
  let values = [];
  for (i = startRow ; i <= lastRow ; i++) {
    let value = sheet.getRange(i, headerLocation.col).getValue();
    if ((value != "") && (values.indexOf(value) == -1)) {
      values.push(value);
    }
  }  
  return values;
}
function getUniqueColumnValues(sheet, headerLocation) {
  let values = [];
  let searchLocation = new Location(sheet, headerLocation.row + 1, headerLocation.col);
  let lastRow = sheet.getLastRow();
  while (searchLocation.row <= lastRow) {
    let value = searchLocation.getValue();
    if (values.indexOf(value) == -1) {
      values.push(value);
    }
    searchLocation.addRow();
  }
  return values;
}