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

发布于 2024-11-08 13:56:50 字数 439 浏览 3 评论 0原文

我有两个字符串数组,长度不一定相同,我想找到数组中两个值之间所有可能的组合“集”,而不从任一数组中重复。
例如,给定数组:
{“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 对字符串数组上运行此代码)。
谁能指导我找到一种有效的方法来做到这一点?

I have two arrays of strings, not necessarily of the same length, I want to find all the possible "sets" of combinations between two values from the arrays, without repeats from either array.
For example, given the arrays:
{ "A1", "A2", "A3" }
{ "B1", "B2" }
The result I want is the following sets:
{ ("A1", "B1"), ("A2", "B2") }
{ ("A1", "B1"), ("A3", "B2") }
{ ("A1", "B2"), ("A2", "B1") }
{ ("A1", "B2"), ("A3", "B1") }
{ ("A2", "B1"), ("A3", "B2") }
{ ("A2", "B2"), ("A3", "B1") }

My general direction is to create recursive function that takes as a parameter the two arrays and removes each "chosen" strings at a time, calling itself until either array is empty, however I'm kinda worried about performance issues (I need to run this code on about a 1000 pairs of string arrays).
Can anyone direct my towards an efficient method to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

等往事风中吹 2024-11-15 13:56:50

将两个数组视为表的两侧可能会有所帮助:

        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|     |     |     |     |     |     |
-----+-----+-----+-----+-----+-----+-----+

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

It might be beneficial to think of the two arrays as sides of a table:

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

This implies a loop nested within another, one loop for the rows and the other for the columns. This will give you the initial set of pairs:

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

Then it is a matter of building up the combinations of that initial set. You can visualise the combinations similarly, with the set of pairs for both the rows and columns:

      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|     |     |     |     |     |     |
-----+-----+-----+-----+-----+-----+-----+

Again this can be accomplished with a pair of nested loops (hint: your inner loop's range will be determined by the outer loop's value).

流云如水 2024-11-15 13:56:50

您的问题相当于以下问题:

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

解决方案
由于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<int> generateArray(int size) {
        vector<int> 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<vector<pair<int, int> > > 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<int> A = generateArray(n);
        vector<int> B = generateArray(m);
        vector<vector<pair<int, int> > > matches;
        // Generate all the permutations of m
        do {
            vector<pair<int, int> > match;
            for (int i = 0; i < n; ++i) {
                pair<int, int> 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;
    }
};

Your problem is equivalent to the following problem:

Problem Statement:
Given two vectors A with size n, B with size m, where n <= m.
A = [0, 1, 2, ..., n - 1].
B = [0, 1, 2, ..., m - 1].
Find all possible injective and non-surjective mappings from A to B.
One possible injective and non-surjective mapping

Solution:
As the size of A is smaller, in one mapping, the number of correspondences is equal to the size of A, i.e., n.

Then we generate all the possible permutations of B, so that the beginning n elements in each permutation can have an one to one correspondence with the elements in A.

The first several permutations and mappings go as follows:
Permutation 1
Permutation 2
Permutation 3
Permutation 4

Implementation:

class Helper {
public:
    /**
     * @brief generateArray
     * @param size
     * @return A vector [0, 1, ..., size - 1]
     */
    vector<int> generateArray(int size) {
        vector<int> 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<vector<pair<int, int> > > 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<int> A = generateArray(n);
        vector<int> B = generateArray(m);
        vector<vector<pair<int, int> > > matches;
        // Generate all the permutations of m
        do {
            vector<pair<int, int> > match;
            for (int i = 0; i < n; ++i) {
                pair<int, int> 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;
    }
};
红墙和绿瓦 2024-11-15 13:56:50

非常简单的方法是

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

very simple way is

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++;
            }
        }
三生池水覆流年 2024-11-15 13:56:50

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

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

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

每个可能的结果都可以写成一个包含 m 个元素的数组 C,其中元素 i 带有值 j,对于 A(i)B(j) 对。排列的总数,即 C 数组,是 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 n-m
             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 只剩下一个元素,递归调用结束。这样就可以了。也许(恕我直言)这与郑金吉的代码答案类似 - (我不能告诉)。我的目的是尝试提供一个简单直观的伪代码版本。可以在此处找到该解决方案在 VB 中的实现。

I looked into this challenge when I saw a crossword style puzzle where each square has a number, and you have to find which letter corresponds to which number in order to make the words correct. Knowing I'm touching answers already given, I'll try to summarize the problem, and show how it can be solved recursively.

In the x-word case, the smaller array A is a series of numbers, and the large array B contains the letters of the alphabet. The problem is to assign each number to a letter, and to find all possible combinations. Generally we have:

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

Each possible result can be written as an array C with m elements, where element i carry the value j, for the pair A(i)B(j). The total number of permutations, i.e. C-arrays, is n(n-1).....(n-m+1) or more neatly written: n!/(m+1)!

This number follows from thinking that when the first element of A is paired with any of the elements in B, the second element of A can be paired with any element except the one that was taken by the first one, and so on and on.

We can achieve this with following pseudo-code:

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 n-m
             C(m)=B'''(x)   'B is now reduced with (m-1) elements
          next x

I use 1-based arrays for intuitivity.

This code would not work for arbitrary length of A, and would be cumbersome to write for large m, so we better make this recursive with a procedure AllPairs, that can call itself:

   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

Note that C initially is an empty array with same size as A (could as well be a copy of A). C remains the same size, while A and B are succesively reduced, until A contains only one element, and the recursive calling ends. This would do it. Perhaps (with all respect) this is similar to the code Jingie Zheng's answer - (I can't tell). My intent here is to try to give an easy intuitive pseudocode version. This solution can be found implemented in VB here.

可是我不能没有你 2024-11-15 13:56:50

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

数组组合数组

Its not quite the same problem, but there's a solution I did to the following question that would probably be a decent start point:

Array of array combinations

⊕婉儿 2024-11-15 13:56:50

本网站上有很多关于两个列表的组合的问题(和答案)(参见侧边栏)。如果我理解正确的话,你的用例看起来只是表面上的不同。

是否就足够了

IEnumerable<Tuple<string, string>> Combinations(
  IEnumerable<string> list1, 
  IEnumerable<string> list2) {}

拥有一个方法(它以各种形式和大小存在于“重复项”中)然后按照以下步骤使用它(家庭作业=您填写详细信息)

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

  • 按当前组合的第一个元素过滤列表 1
  • 按当前组合的第二个元素过滤列表 2
  • 将当前组合与过滤列表的所有可能组合组合(使用类似以下方法的内容)多于)

There are lots of questions (and answers) regarding combinations of two lists on this site (see sidebar). Your use case seems only superficially different if I understand it correctly.

Wouldn't it suffice to have a method

IEnumerable<Tuple<string, string>> Combinations(
  IEnumerable<string> list1, 
  IEnumerable<string> list2) {}

(which exists in various forms and sizes already in the 'duplicates') and then use that by following these steps (homework = you fill in the details):

Iterate over all combinations of list 1 & list 2 (using something like the above) and

  • Filter list 1 by the first element of the current combination
  • Filter list 2 by the second element of the current combination
  • Combine the current combination with all possible combinations of the filtered lists (using something like the method above)
◇流星雨 2024-11-15 13:56:50

如果我正确理解你的问题,所有组合都可以导出:

  • 从 A 中选择 2 个不同的元素 {A_i, A_j}
  • 从 A 中选择 2 个不同的元素 {B_k, B_l} B,
  • 用这些元素 { (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 组合。

简单的实现是通过 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)}

If I understand your problem correctly, all combinations can be derived with:

  • chose 2 different elements {A_i, A_j} from A,
  • chose 2 different elements {B_k, B_l} from B,
  • make 2 combinations with these elements { (A_i, B_k), (A_j, B_l) }, { (A_i, B_l), (A_j, B_k) }.

With all combinations of 2 element subsets from A and B, you get all combinations you are looking for.

There are |A| * (|A| - 1) * |B| * (|B| - 1) / 2 combinations.

Easies implementation is with 4 loops:

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)}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文