我该如何在 Perl 中表示集合?

41

我想在Perl中表示一个集合。我通常使用带有一些虚拟值的哈希表来实现,例如:

my %hash=();
$hash{"element1"}=1;
$hash{"element5"}=1;

使用 if (defined $hash{$element_name}) 来判断元素是否在集合中。

这是一种常见的做法吗?有没有改进建议?

此外,我应该使用 defined 还是 exists

谢谢

3个回答

56

是的,用这种方式构建哈希集是一种常见的习惯用法。请注意:

my @keys = qw/a b c d/;
my %hash;
@hash{@keys} = ();

使用undef作为值要比使用1更好,因为undef占用的空间显著更少。这还强制你使用exists(这本来就是正确的选择)。


+1 谢谢。请查看关于“深度集合”的相关问题:https://dev59.com/K3A65IYBdhLWcg3wqQc8 - David B

15

使用CPAN上的众多Set模块之一。从您的示例来看,Set::LightSet::Scalar似乎是合适的选择。


我可以用通常支持使用CPAN的论点来为这个建议辩护(不考虑可能的协同效应)。

  1. 我们怎样才能知道现在和未来只需要查找?经验教导我们即使是最简单的程序也会膨胀和扩展。使用一个模块将会预见到这一点。
  2. API比临时实现更好维护,或对于需要阅读和理解代码的人而言更易于理解,因为它允许在不同层面上思考部分问题。
  3. 与此相关的是,如果结果表明开销不可取,那么通过消除间接引用或缩小数据结构和源代码可以从模块转换为简单。但是,在另一个方向上需要更多功能时,则相对困难一些。
  4. CPAN模块已经得到测试并在某种程度上得到彻底的调试,也许API随着时间的推移也经历了改进,而使用临时实现,程序员通常会实现首先想到的设计

很少情况下,在开始选择模块时选择错误。


3
除了开销外,它们还能提供什么?如集合操作或其他内容吗?如果我只是检查集合中是否存在某个项,为什么要使用库来执行语言已经非常擅长的任务? - Chas. Owens
有哪些支持集合嵌套的模块建议? - David B
集合的集合听起来像是 Set::Object 的一项任务,它的实例可以嵌套。 - daxim
7
为什么要使用库?这样你的代码阅读起来就像它在做什么,而不是如何做到。$set->insert('foo') 明确表示您正在将 'foo' 插入到一个集合中。$hash{foo} = 1 看起来像是将 foo 映射到 1,但实际上并不是这样。加入成员测试的混合使用,其中 defined 和 exists 同样适用,当你开始混合使用两者时,事情可能变得混乱。或者当您开始使用 = 0 来从集合中删除某些内容,但在其他地方使用 exists 检查时。基本上,使用哈希作为集合很难阅读和维护。另外,Set::Object 比哈希更快。 - jrockway

2

这就是我一直以来的做法。我倾向于使用exists而不是defined,但在这种情况下它们都应该可以使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接