【问题标题】:How to perform Cartesian Join with Google Scripts & Google Sheets?如何使用 Google Scripts 和 Google Sheets 执行笛卡尔连接?
【发布时间】:2021-04-09 21:24:10
【问题描述】:

我找到了基本 2 列笛卡尔连接的代码,但情况略有不同。

有 3 个变量/列:颜色、颜色 ID 和项目。

我想要颜色和物品的每一种组合。我想通过颜色变量将第三个变量颜色 ID 附加到臀部。

这是一个示例电子表格。 A-C 列是输入数据,E-G 列是所需输出(顺序不重要。)

https://docs.google.com/spreadsheets/d/1LgWttzY317T3N66Wk2JbDq8nETSGl1HCxY8u8i0jhl4/edit#gid=0

【问题讨论】:

  • 请使用表格来提供数据结构而不是工作表的链接。

标签: javascript google-apps-script google-sheets google-sheets-formula cartesian-product


【解决方案1】:

我相信你的目标如下。

  • 您希望使用 Google Apps 脚本实现以下转换。

    • 来自

        Blue   74  Shirt
        Red    48  Pants
        Green  55  Shoes
                   Hat
                   Socks
                   Backpack
      
    •   Blue   74  Shirt
        Blue   74  Pants
        Blue   74  Shoes
        Blue   74  Hat
        Blue   74  Socks
        Blue   74  Backpack
        Red    48  Shirt
        Red    48  Pants
        Red    48  Shoes
        Red    48  Hat
        Red    48  Socks
        Red    48  Backpack
        Green  55  Shirt
        Green  55  Pants
        Green  55  Shoes
        Green  55  Hat
        Green  55  Socks
        Green  55  Backpack
      
  • 在您的示例电子表格中,Green, 55 具有相同的值,即Backpack。但从您的示例模式来看,我认为您可能想要 avove 转换。

如果我的理解是正确的,我想提出以下流程。

  1. 检索“A”到“C”列中的值。
  2. 转置检索到的值。
  3. 创建用于放入电子表格的数组。
  4. 输入值。

当上述流程反映到脚本时,变成如下。

示例脚本:

请将以下脚本复制并粘贴到电子表格的脚本编辑器中,然后运行myFunction。这样,结果值将被放入“I2:K”列。

function myFunction() {
  const sheetName = "Sheet1";  // Please set the sheet name.

  // 1. Retrieve the values from the columns "A" to "C".
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
  const values = sheet.getRange("A2:C" + sheet.getLastRow()).getValues();

  // 2. Transpose the retrieved values.
  const [color, id, item] = values[0].map((_, i) => values.map(r => r[i]).filter(String));

  // 3. Create the array for putting to Spreadsheet.
  const res = color.flatMap((e, i) => item.map(g => [e, id[i], g]));

  // 4. Put the values.
  sheet.getRange(2, 9, res.length, res[0].length).setValues(res);
}

结果:

为您的示例电子表格运行上述脚本时,将获得以下结果。

参考资料:

【讨论】:

    【解决方案2】:

    作为一个简单的 Google 表格公式,

    • 用分隔符? 连接AB
    • 将上述结果与TRANSPOSEd C 和分隔符连接起来。这将创建一个笛卡尔积矩阵
    • FLATTEN以上结果
    • SPLIT 由分隔符重新获得 3 列。

    =ARRAYFORMULA(SPLIT(FLATTEN(A2:A4&"?"&B2:B4&"?"&TRANSPOSE(C2:C7)),"?"))
    
    • 如果您想要一个开放式范围,请使用 INDEX/COUNTA

    【讨论】:

    • 您能否详细说明如何将INDEX/COUNTA 用于开放式范围?我认为将A2:A4A2:INDEX(A2:A,COUNTA(A2:A)) 切换等可以解决问题,但这不起作用。也非常感谢您提供这个解决方案,它非常酷。
    • @Wellwoah 这应该可以解决问题。你能显示完整的修改公式和错误吗?
    【解决方案3】:

    Tanaike's answer 很棒,请接受他的回答,但这只是以防万一您想在工作表中将其用作自定义函数(公式):

    function cartesian(startCol) {
      const sh = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
      const vals = sh.getRange(2, startCol, sh.getLastRow(),3).getValues();
      const input  = [...Array(3)].map((_, i) => 
                     vals.map(r => r[i]).
                     filter(e=>e!=''));
      const res = input[0].map((color, i) => 
                  input[2].
                  map(item => [color, input[1][i], item])).
                  flat();
      return res;
    }
    

    然后使用=cartesian(startCol) 其中startCol 在您的情况下为1 作为输入数据的第一列:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-06
      • 2020-07-13
      • 2015-11-18
      • 2020-05-19
      • 2019-04-07
      • 2020-03-07
      • 1970-01-01
      相关资源
      最近更新 更多