【问题标题】:Gathering all the unique values from one column and outputting them in another column..?从一列收集所有唯一值并将它们输出到另一列..?
【发布时间】:2013-06-26 16:14:10
【问题描述】:

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

 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 列,包括新的输出列。)

提前致谢。

附: 我在这里搜索了这个,但我只收到与删除重复行有关的问题。如果有问题已经问到这个问题,请给我链接。

【问题讨论】:

    标签: google-apps-script google-sheets output unique-values


    【解决方案1】:

    您可以在 google-spreadsheets 中使用 UNIQUE 函数执行此操作。
    Here is the doc to all available functions
    (您可以在 Filter 类别中找到 UNIQUE

    您很可能希望插入单元格E1

    =UNIQUE(D1:D)
    

    这将使用来自所有列 D 的唯一值填充列 E,同时保留顺序。此外,这将动态更新并反映对列 D 所做的所有更改。

    google-apps-script 中执行此操作:

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

    【讨论】:

    • 嗯...这似乎太简单了!谢谢!我敢打赌,上面 Serge 的代码之类的东西最终会出现在这个 UNIQUE 函数的后面。
    • 有没有办法使用公式来返回脚本中的值,而不是在电子表格中设置?我有一个用例,我只需要脚本中的数据而不需要将其放入工作表中。
    • @greatwitenorth 如果您对刚才提出的问题找到任何答案,如果我们可以将返回的值存储到数组中,请帮我一个忙并将其发布到某个地方。它会帮助我很多。谢谢!!
    【解决方案2】:

    这是一种方法……可能不是唯一的,但可能还不错……

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

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

    编辑:

    按照 Theodros 的回答,电子表格公式确实是一个优雅的解决方案,我从没想过,但我应该! ;-)

    =SORT(UNIQUE(D1:D))
    

    给出完全相同的结果...

    【讨论】:

    • 再次感谢。该代码也可以完美且快速地运行。一个问题是“for循环”的语法是什么......? (nn in data 部分。)我一直认为你必须这样做:(nn=0; nn&lt;=data.length; nn++) 我试图找到这种格式的文档,但一直碰壁。你的格式会缩短我的很多旧脚本。再次感谢! :)
    • 这只是一个缩写形式,通常它包含这样的 var 声明:for(var nn in data){... 但“正常方式”几乎相同,在这种情况下它应该是 for(var nn=0;nn&lt;data.length;nn++){ 而不是&lt;= 因为我们从 0 开始,数据长度给出从 1 开始的长度;-)。请注意,一些 JS 专家说,简短形式在某些情况下会带来一些问题,但这超出了我的知识范围……我个人从未遇到过任何问题。
    • 很高兴,很高兴为您提供帮助。:-)
    • 在同一主题上查看this post ;-)
    • 是的,在您对我感兴趣之后,我实际上就该主题进行了研究。我从来不知道即使是一个简单的“for”循环也有这么多的复杂性。
    【解决方案3】:

    目前,在 V8 引擎中,最简单的方法是使用Set

    /**
     * @returns {Object[]} Gets unique values in a 2D array
     * @param {Object[][]} array2d
     * @private
     */
    const getUnique_ = array2d => [...new Set(array2d.flat())];
    
    /**
     * Gets Values from a column, makes it unique and sets the modified values
     *   to the next column
     * @param {string} sheetName
     * @param {number} column Number of the column to uniquify
     * @param {number} headers Number of headers
     * @returns void
     */
    const uniquifyAColumn = (sheetName = 'Sheet1', column = 3, headers = 1) => {
      const sh = SpreadsheetApp.getActive().getSheetByName(sheetName),
        rg = sh.getRange(1 + headers, column, sh.getLastRow() - headers, 1),
        values = rg.getValues(),
        uniqueValues = getUnique_(values).map(e => [e]);
      rg.offset(0, 1, uniqueValues.length).setValues(uniqueValues);
    };
    

    【讨论】:

    • 使用 map 效果很好,但我包括检查以确保开始行和要搜索的行在获取范围之前有效。
    【解决方案4】:

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

    headerLocation 是一个 Location 对象:

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

    或者,使用位置来查找值:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-17
      • 2023-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-03
      • 2022-07-07
      • 2023-01-16
      相关资源
      最近更新 更多