如何在Google表格中创建所有可能的配对组合而不重复?

时间:2017-12-21 09:54:59

标签: excel excel-formula google-sheets iteration

如何对excel / google工作表单元格进行迭代以获得成对组合?

"string1"

"string2"
"string3"
...
"string10"

我正在考虑编写一个可以迭代这些字符串的函数来创建以下内容:

"string1, string2" 
"string1, string 3" 
...
"string 1, string 10" 
"string 2, string 3" 
...
"string 2, string 10" 
"string3, string 4" 
... ... 
"string9 string10".

这可以在谷歌表吗?

4 个答案:

答案 0 :(得分:1)

本机功能是一项艰巨的任务。尝试使用脚本并将其用作自定义函数:

function getTournament(teams_from_range)

    {
      // teams_from_range -- 2D Array  
      var teams = [];
      // convert to list
      teams_from_range.forEach(function(row) { row.forEach(function(cell) { teams.push(cell); } ); } );
      return getTournament_(teams);
    }


    function getTournament_(teams)
    {
      var start = 0;
      var l = teams.length;
      var result = [], game = [];

      // loop each value
      for (var i = 0; i < l; i++)
      {
        // loop each value minus current
        start++;
        for (var ii = start; ii < l; ii++)
        {
          game = []
          game.push(teams[i]);
          game.push(teams[ii]);  
          result.push(game);
        }  
      }

      return result;

    }

用法:

=getTournament(A1:A10)

答案 1 :(得分:1)

我不得不同意@Max认为本机功能很难,或者至少是啰嗦,但可以在Google表格中使用

=ArrayFormula(query({if((row(A:A)<=counta(A:A)^2)*(int((row(A:A)-1)/counta(A:A))<mod((row(A:A)-1),counta(A:A))),
vlookup(int((row(A:A)-1)/counta(A:A)),{row(A:A)-1,A:A},2)&vlookup(mod((row(A:A)-1),counta(A:A)),{row(A:A)-1,A:A},2),"")},"select Col1 where Col1<>''"))

enter image description here

注1 - 方法

使用10个字符串的列表作为示例。

(1)使用

添加一列以对0到9之间的字符串进行编号

{行(A:A)-1,A:A}

(2)使用VLOOKUP中的行号来获取该对的第一个字符串

VLOOKUP(INT((行(A:A)-1)/ COUNTA(A:A)),{行(A:A)-1,A:A},2)

Row number-1 int((row(A:A)-1)/counta(A:A))  String

0            0                              String1

1            0                              String1

...

9            0                              String1

10           1                              String2

...

20           2                              String3

...

99           9                              String10

(3)使用VLOOKUP中的行号来获取

对中的第二个字符串

VLOOKUP(MOD((行(A:A)-1),COUNTA(A:A)),{行(A:A)-1,A:A},2)

Row number-1  mod((row(A:A)-1),counta(A:A)) String

0             0                             String1

1             1                             String2

2             2                             String3

...

9             9                             String10

10            0                             String1

11            1                             String2

...

99            9                             String10

请注意,该列表将包含不需要的对,如String1String1和String2String1。

(4)使用if条件

将不需要的对设置为“”

如果((行(A:A)LT = COUNTA(A:A)^ 2)*(INT((行(A:A)-1)/ COUNTA(A:A))

注1 按照@Max Makhrov的建议,使用过滤器删除不需要的对会更短。

(5)使用Query删除空行。

注2 - 行数限制

因为生成了冗余对然后被移除,所以这种方法要求N ^ 2行在片材中,其中N是字符串的数量而不是N *(N-1)/ 2,这是N的不同对的数量对象。相反,对于具有N行的薄片,可以这种方式处理的字符串s的最大数量是floor(sqrt(N)),例如,对于包含1,000行的工作表s = floor(sqrt(1000))= 31。

注3 - 避免生成冗余对的可能方法

可视化我尝试做的事情的一种方法如下,其中数组元素表示输出行(A:A),行和列标题指示相应的值,这些值用作查找以获取对象(字符串1) ,string 1),(string 1 string 2)等。

enter image description here

使用整数除法和MOD函数从输出行到查找值的映射相当容易。

我们真正想做的是获得像这样的非冗余对

enter image description here

但是那么如何从输出行1-10映射到查找值对1-5?

我希望通过一些数学提供(至少在原理上)一种方法来直接获得N(N-1)/ 2个非冗余对而不首先生成所有N ^ 2对,这是可能的。

上面三角形部分的行1到r中的单元的计数S是总计数N(N-1)/ 2减去它下面的行中的计数(Nr)(Nr-1)/ 2 < / p>

enter image description here

这可以重新安排如下

enter image description here

这是r中的二次方,所以我们可以使用常规公式

来解决它

enter image description here

给予

enter image description here

因此,行由r。

的上述公式的上限给出

r行末尾的数字(比如T)是用r的上限代替上面的第二个等式给出的

enter image description here

最后对应于S的列由

给出

enter image description here

现在定义一个名为

的命名范围N.
=counta(A:A)

和命名范围M,其值为

=2*N-1

然后最后你需要选择stringA(矩阵的行r)的公式是

=iferror(ArrayFormula(vlookup(ceiling((M-sqrt(M^2-8*row(A:A)))/2,1),{row(A:A),A:A},2)),"")

和选择stringB(矩阵的列c)所需的公式是

=iferror(ArrayFormula(vlookup(N+row(A:A)-(M*CEILING((M-SQRT(M^2-8*row(A:A)))/2,1)-CEILING((M-SQRT(M^2-8*row(A:A)))/2,1)^2)/2,{row(A:A),A:A},2)),"")

enter image description here

其中包含D和E列用于测试目的。

然后,如果需要,它只会将两个公式合并为一列。

答案 2 :(得分:0)

=QUERY(ARRAYFORMULA(SPLIT(
 TRANSPOSE(SPLIT(REPT(CONCATENATE(A2:A&CHAR(9)), COUNTA(A2:A)),  CHAR(9)))& " "&
 TRANSPOSE(SPLIT(CONCATENATE(REPT(A2:A&CHAR(9),  COUNTA(A2:A))), CHAR(9))), " ")),
 "where Col1<>Col2 order by Col1", 0)

答案 3 :(得分:0)

=ARRAYFORMULA(SPLIT(SORT(
 TRANSPOSE(SPLIT(CONCATENATE(REPT(UNIQUE(TRANSPOSE(SPLIT(JOIN(",",TEXTJOIN(",",1,A2:A)),",")))&","&
 TRANSPOSE(UNIQUE(TRANSPOSE(SPLIT(JOIN(",",TEXTJOIN(",",1,A2:A)),",")))), (
 UNIQUE(TRANSPOSE(SPLIT(JOIN(",",TEXTJOIN(",",1,A2:A)),",")))<=
 TRANSPOSE(UNIQUE(TRANSPOSE(SPLIT(JOIN(",",TEXTJOIN(",",1,A2:A)),",")))))*
 REGEXMATCH(CONCATENATE(","&SUBSTITUTE(TEXTJOIN(",",1,A2:A),",",",,")&","&CHAR(9)),"(,"&
 UNIQUE(TRANSPOSE(SPLIT(JOIN(",",TEXTJOIN(",",1,A2:A)),",")))&",[^\t]*,"&
 TRANSPOSE(UNIQUE(TRANSPOSE(SPLIT(JOIN(",",TEXTJOIN(",",1,A2:A)),","))))&",)|(,"&
 TRANSPOSE(UNIQUE(TRANSPOSE(SPLIT(JOIN(",",TEXTJOIN(",",1,A2:A)),","))))&",[^\t]*,"&
 UNIQUE(TRANSPOSE(SPLIT(JOIN(",",TEXTJOIN(",",1,A2:A)),",")))&",)"))&CHAR(9)),CHAR(9)))),","))

0