3

我有一张包含以下数据的表格

1.1.1.1   routerA  texas
2.2.2.2   routerB  texas
3.3.3.3   routerC  california

Perl 中存储这些数据的最佳数据结构是什么?我正在考虑将 IP 地址作为密钥存储在哈希哈希中

1.1.1.1 
 routerA => texas,
2.2.2.2
 routerB => texas,
3.3.3.3
 routerC => california

但是如果我想获取德州的所有IP地址,我的数据结构可能不够灵活。如果我关心德克萨斯州的所有 IP 地址,是否有更好的方法来存储它?

4

3 回答 3

10

Pure Perl 绝对可以胜任这项任务。

将表视为记录数组。在 Perl 中,这是一个哈希引用数组。(AoA 有时可能适用,记住 TIMTOWTDI)

每个哈希引用的键对应于列/字段名称,而值将是该特定记录的值。

将 OP 的示例转换为数据结构:

my @data = (
             {
                ip     => '1.1.1.1',
                router => 'routerA',
                state  => 'texas',
             },
             {
                ip     => '2.2.2.2',
                router => 'routerB',
                state  => 'texas',
             },
             {
                ip     => '3.3.3.3',
                router => 'routerA',
                state  => 'california',
             }
           );

现在是有趣的部分:

# Give me all IPs in Texas

my @ips_in_texas = map $_->{ip},
                    grep { $_->{state} =~ /texas/i }
                     @data;

# How many states does the data cover?

use List::MoreUtils 'uniq';

my $states_covered = uniq( map $_->{state}, @data );

# How many unique IPs in each state?

my %ips_by_state;
$ips_by_state{ $_->{state} }{ $_->{ip} }++ for @data;
print "'$_': ", scalar keys %{ $ips_by_state{$_} }, "\n" for keys %ips_by_state;

当我建议这种数据结构围绕其对内存的渴望时,我经常会得到下意识的反应。坦率地说,除非您处理数百万条记录,否则这不是问题。如果是这样的话,DBMS 是您寻求的锐化铅笔解决方案,而不是 Perl。

于 2012-06-04T16:17:43.630 回答
4

您建议使用带有 IP 地址的哈希值作为密钥,这正是我将如何做到的。但是,您还必须构建一个单独的、辅助的、交叉引用的哈希,其中州(如德克萨斯州)是键,IP 地址是数据。在二级散列中,每个状态都是一个键,对应的值本身就是一个散列。在内部散列中,键是 IP,值是虚拟值,通常是值 1。

在您的示例中,这是辅助的交叉引用哈希:

california
 { 3.3.3.3 => 1 },
texas
 { 1.1.1.1 => 1, 2.2.2.2 => 1 }

您可以编写一个简短的子例程/函数/块,从主散列构建辅助散列。如果数据集很大并且经常更新,这会有点困难,但想法是一样的。

如果您首先掌握 Perl 几乎太可爱但仍然相当方便的自动激活功能,您会发现编写执行上述操作的代码会更容易请参阅手册页 perlreftutperlref。

于 2012-06-04T15:57:47.380 回答
4

我知道,这不是 perl ......但是内存中的SQLite表怎么样?快速、灵活、便携甚至持久。你可以在那里做很多更复杂的事情,然后在德克萨斯州寻找所有 IP ......

于 2012-06-04T15:41:03.803 回答