两个列表中所有可能的对列表

时间:2011-04-18 21:13:05

标签: algorithm recursion combinations

假设我有两个项目列表。这两个列表的长度可能相同,也可能不同。

如何生成所有可能的项目对的所有列表,其中一对项目包含每个列表中的项目?每个项目只能在一对中。

所以,如果一个列表是:

(1, 2, 3)

另一个清单是:

(a, b)

然后所有可能的对的列表将是:

(1a, 2b)
(1a, 3b)
(1b, 2a)
(1b, 3a)
(2a, 3b)
(2b, 3a)

(我在Perl中实现了这一点,但显然算法很重要。)

提前致谢。我的递归foo无效!

1 个答案:

答案 0 :(得分:0)

以下是示例代码。

use strict;
use warnings;

sub unordered_pairs {
    return if @_ < 2;
    my $first = shift;
    return (map [$first, $_], @_), unordered_pairs(@_);
}

sub cartesian_product {
    my @answers = [];
    for my $list (@_) {
        @answers = map {
            my $value = $_;
            map [@$_, $value], @answers
        } @$list;
    }
    return @answers;
}

sub possible_pairs_of_pairs {
    my ($list1, $list2) = @_;

    my @pairs1 = unordered_pairs(@$list1);
    my @pairs2 = unordered_pairs(@$list2);

    return map {
        [[$_->[0][0], $_->[1][0]], [$_->[0][1], $_->[1][1]]],
        [[$_->[0][0], $_->[1][1]], [$_->[0][1], $_->[1][0]]],
    } cartesian_product(\@pairs1, \@pairs2);
}

样本用法:

use Data::Dumper;
my @stuff = possible_pairs_of_pairs([1, 2, 3], ['a', 'b']);
print Dumper(\@stuff);

请注意,如果您的列表包含$n$m元素,则最终输出将包含$n * ($n-1) * $m * ($m-1) / 2个元素。使用较大的列表会很快爆炸。请阅读http://perl.plover.com/Stream/stream.html,了解如何使用这种数据结构不会耗尽内存。 (或阅读 Higher Order Perl ,这篇最终出自该文章的书。)