我是perl的新手,我已经坚持了几天。希望你能帮帮我。
我使用两个文件,我将简化,因为我必须事先处理它们:
file_one
的{{1}}列表{name1,name_2,name_3 ...)和names
(number_1,number_2,number_3 ...)分别关联
numbers
列有file_two
(number_2和number_6)和numbers
(item_a,item_b与number_2相关联,item_b,item_c与number_6相关联)
我的想法是对两个文件进行哈希并将它们组合起来。我遇到的问题是当我需要将项目列表加入哈希(数组的哈希)然后使用它时。所以第一个哈希工作正常,但第二个哈希有问题。
我尝试使用items
,但由于我使用的引用,我不知道如何将它与另一个结合起来。
最后的任务是比较两个名字,以便获得他们共享的项目。如果可以使用perl并且如果可能的话不使用模块,那将会很棒。
非常感谢
答案 0 :(得分:2)
如果我正确理解你,你就有这个:
foo => 1
bar => 2
baz => 3
然后你有:
2 => a, b
3 => b, c
您想了解bar
和baz
分享的内容(例如)。
一种选择是将它们放在SQLite数据库中的两个表中并使用SQL。这可以是处理这样的关系数据的最简单,最灵活,最高效的方式。特别是如果它有很多,特别是如果你想对它做很多不同的搜索。这避免了必须编写一堆自定义代码和可能日益复杂的数据结构。
在Perl中完成它,这是一个草图。
首先,将包含叶子(项目不指向任何其他内容)的第二个文件读入数组的哈希值。你结束了这样的结构:
$nums2items{2} = [qw(a, b)];
然后将第一个文件读入哈希,但不是将数字存储为值,而是存储%nums2items
个引用。
$names2items{foo} = $nums2items{1};
现在,如果您想检查bar
和baz
是否共享任何内容,您可以获取数组并找到与Array::Utils的交集。
use Array::Utils qw(intersect);
print join ", ", intersect( @{$names2items{bar}}, @{$names2items{baz}});
如果您要做很多事情,并且项目的顺序无关紧要,那么将项目存储为哈希会更有效。这避免了必须对两个列表进行排序和比较。这就是intersect
无论如何,将一个列表转换为一个哈希(或一组)并将其与另一个列表进行比较。
use strict;
use warnings;
use v5.10;
my %nums2items = (
2 => { a => 1, b => 1, d => 1 },
3 => { b => 1, c => 1, d => 1, e => 1 },
);
my %names2nums = (
bar => $nums2items{2},
baz => $nums2items{3}
);
# Take the intersection in O(n) time.
say join ", ", grep { $names2nums{bar}{$_} } keys %{$names2nums{baz}};
使用像那样的哈希,其中键是事物而值是1,是表示集合的一种非常常见且有效的方式。
或者您可以使用Set::Tiny模块。这非常直截了当。如果你想学习如何在Perl中使用集合,我强烈建议你阅读它的来源。
答案 1 :(得分:0)
从您对Schwern的评论看来,您的文件看起来像这样:
foo, 1
bar, 2
biz, 3
bas, 4
和
1, jacks blue horse
2, the green horse
3, jacks
4, bing
并且您成功地将它们读入两个哈希值,其中以逗号作为键之前的值以及之后的值作为值。现在你要采取明智的措辞,打印出他们共同的话语。您不想使用任何模块,而是使用原始Perl。
首先,为什么第二个是数组数组而不是哈希值,如果它是数字键控的话?
其次,你为什么要合并它们?为什么不使用嵌套循环:
my @key_list = keys %hash_1;
while ( @key_list )
{
my $curr_key = shift @key_list;
for my $next_key ( @key_list )
{
my @curr_list = @{$hash_2{$hash_1{$curr_key}}};
my @next_list = @{$hash_2{$hash_1{$next_key}}};
while ( @curr_list )
{
my $curr_word = shift @curr_list;
for my $next_word ( @next_list )
{
print "$curr_key and $next_key share $curr_word\n"
if $curr_word eq $next_word;
}
}
}
}
这有点蛮力,但它可以完成工作。相反,你可以使用优秀的Set :: modules。了解和使用像Perl或C ++这样的现代语言的一部分就是了解标准库和通用库并使用它们。