查找两个数组之间的所有可能值组合

我有两个字符串数组,不一定长度相同,我想找到数组中两个值之间所有可能的“组合”组合,而不是从任何一个数组重复。
例如,给定数组:
{“A1”,“A2”,“A3”}
{“B1”,“B2”}
我想要的结果是以下几组:
{(“A1”,“B1”),(“A2”,“B2”)}
{(“A1”,“B1”),(“A3”,“B2”)}
{(“A1”,“B2”),(“A2”,“B1”)}
{(“A1”,“B2”),(“A3”,“B1”)}
{(“A2”,“B1”),(“A3”,“B2”)}
{(“A2”,“B2”),(“A3”,“B1”)}

我的总体方向是创建递归函数,它将两个数组作为参数并一次删除每个“选定”字符串,调用自身直到任一数组为空,但我有点担心性能问题(我需要运行它大约1000对字符串数组的代码)。
任何人都可以指导我采用有效的方法来做到这一点吗?

将两个数组视为表的一侧可能是有益的:

  A1 A2 A3 ---+-------+-------+-------+ B1 | B1,A1 | B1,A2 | B1,A3 | ---+-------+-------+-------+ B2 | B2,A1 | B2,A2 | B2,A3 | ---+-------+-------+-------+ 

这意味着一个循环嵌套在另一个循环中,一个循环用于行,另一个循环用于列。 这将为您提供一组初始对:

 {B1,A1} {B1,A2} {B1,A3} {B2,A1} {B2,A2} {B2,A3} 

然后是建立初始集的组合的问题。 您可以使用行和列的对集合来可视化组合:

  B1,A1 B1,A2 B1,A3 B2,A1 B2,A2 B2,A3 -----+-----+-----+-----+-----+-----+-----+ B1,A1| | X | X | X | X | X | -----+-----+-----+-----+-----+-----+-----+ B1,A2| | | X | X | X | X | -----+-----+-----+-----+-----+-----+-----+ B1,A3| | | | X | X | X | -----+-----+-----+-----+-----+-----+-----+ B2,A1| | | | | X | X | -----+-----+-----+-----+-----+-----+-----+ B2,A2| | | | | | X | -----+-----+-----+-----+-----+-----+-----+ B2,A3| | | | | | | -----+-----+-----+-----+-----+-----+-----+ 

同样,这可以通过一对嵌套循环来完成(提示:您的内循环的范围将由外循环的值确定)。

非常简单的方法是

 string[] arr = new string[3]; string[] arr1 = new string[4]; string[] jointarr = new string[100]; for (int i = 0; i < arr.Length; i++) { arr[i] = "A" + (i + 1); } for (int i = 0; i < arr1.Length; i++) { arr1[i] = "B" + (i + 1); } int k=0; for (int i = 0; i < arr.Length; i++) { for (int j = 0; j < arr1.Length; j++) { jointarr[k] = arr[i] + " " + arr1[j]; k++; } } 

您的问题等同于以下问题:

问题陈述:
给定两个大小为n向量A ,大小为n B ,其中n <= m
A = [0, 1, 2, ..., n - 1]
B = [0, 1, 2, ..., m - 1]
找到从AB所有可能的内射和非射影映射 。 一种可能的内射和非射影映射

方案
由于A的大小较小,在一次映射中,对应的数量等于A的大小,即n。

然后我们生成B的所有可能的排列,使得每个排列中的起始n个元素可以与A中的元素一一对应。

前几个排列和映射如下: 排列1排列2排列3排列4

执行:

 class Helper { public: /** * @brief generateArray * @param size * @return A vector [0, 1, ..., size - 1] */ vector generateArray(int size) { vector arr; for (int i = 0; i < size; ++i) { arr.push_back(i); } return arr; } /** * @brief generateMatches * @param n, cardinality of the vector X, where X = [0,1, ..., n - 1]. * @param m, cardinality of the vector Y, where Y = [0,1, ..., m - 1]. * @return All possible injective and non-surjective mappings * from the smaller vector to the larger vector. */ vector > > generateMatches(int n, int m) { // Deal with n > m. Swap back when generating pairs. bool swapped = false; if (n > m) { swapped = true; swap(n, m); } // Now n is smaller or equal to m vector A = generateArray(n); vector B = generateArray(m); vector > > matches; // Generate all the permutations of m do { vector > match; for (int i = 0; i < n; ++i) { pair p; if (swapped) { // Swap back to the original order. p = make_pair(A[i], B[i]); } else { p = make_pair(B[i], A[i]); } match.push_back(p); } matches.push_back(match); // Generate next permutation. } while(next_permutaion(B.begin(), B.end())); return matches; } }; 

这不是同一个问题,但是我对以下问题做了一个解决方案,这可能是一个不错的起点:

数组组合的数组

关于本网站上两个列表的组合有很多问题(和答案)(见附文)。 如果我理解正确,你的用例似乎只是表面上不同。

有一个方法是不够的

 IEnumerable> Combinations( IEnumerable list1, IEnumerable list2) {} 

(已经在’重复’中以各种forms和大小存在),然后按照这些步骤使用它(homework =你填写详细信息):

迭代列表1和列表2的所有组合(使用类似上面的内容)和

  • 按当前组合的第一个元素过滤列表1
  • 按当前组合的第二个元素过滤列表2
  • 将当前组合与过滤列表的所有可能组合相结合(使用类似上述方法的方法)

如果我正确理解您的问题,可以使用以下方法派生所有组合:

  • 从A中选择了2个不同的元素{A_i, A_j}
  • 从B中选择了2个不同的元素{B_k, B_l}
  • 与这些元素{ (A_i, B_k), (A_j, B_l) }, { (A_i, B_l), (A_j, B_k) }进行2种组合。

通过A和B中2个元素子集的所有组合,您可以获得所需的所有组合。

|A| * (|A| - 1) * |B| * (|B| - 1) / 2 |A| * (|A| - 1) * |B| * (|B| - 1) / 2 |A| * (|A| - 1) * |B| * (|B| - 1) / 2组合。

易于实现的是4个循环:

 for i = 1 ... |A| for j = i+1 ... |A| for k = 1 ... |B| for l = k+1 ... |B| make 2 combinations {(A_i, B_k),(A_j, B_l)}, {(A_i, B_l), (A_j, B_k)} 

当我看到一个填字游戏风格拼图时,我调查了这个挑战,其中每个方格都有一个数字,你必须找到哪个字母对应于哪个数字才能使单词正确。 知道我已经触及已经给出的答案,我将尝试总结问题,并展示如何以递归方式解决问题。

在x字的情况下,较小的数组A是一系列数字,而大数组B包含字母表的字母。 问题是将每个数字分配给一个字母,并找到所有可能的组合。 一般来说我们有:

 A={1,2,...m} and B={1,2,....n} n>=m 

对于对A(i)B(j),每个可能的结果可以写为具有m个元素的数组C,其中元素i携带值j。 排列的总数,即Carrays,是n(n-1)…..(n-m + 1)或更整齐地写:n!/(m + 1)!

这个数字来自于认为当A的第一个元素与B中的任何元素配对时,A的第二个元素可以与第一个元素之外的任何元素配对,依此类推。

我们可以通过以下代码来实现:

 for i= 1 to n C(1)=B(i) for j= 1 to n-1 C(2)=B'(j) ' B' is B with element i removed ......... for x = 1 to nm C(m)=B'''(x) 'B is now reduced with (m-1) elements next x 

我使用基于1的数组来实现直观性。

这段代码对于任意长度的A都不起作用,并且为大m编写会很麻烦,所以我们最好使用一个可以调用自身的过程AllPairs进行递归:

  AllPairs (A,B,C) if Size(A)>1 ' check no of elements in A for i=1 to Size(B) C(Size(C)-Size(A)+1)= B(i) A'=Remove element 1 from A B'=Remove element i from B Call AllPairs(A',B',C) 'recursive call Next i else ' only one element in A for j=1 to Size(B) C(Size(C)) = B(i) 'looping last element in C through all unused in B Collect.ADD(C) 'collect C-arrays here for later use Next j End AllPairs 

注意,C最初是一个与A大小相同的空数组(也可以是A的副本)。 C保持相同的大小,而A和B连续减少,直到A只包含一个元素,递归调用结束。 这样做会。 也许(尽管如此)这类似于代码Jingie Zheng的答案 – (我不知道)。 我的目的是尝试提供一个简单直观的伪代码版本。 这个解决方案可以在这里用VB实现。