我正在尝试制作一个简单的 Perl 脚本来获取一系列数字(0..255
),遍历每个数字并找到不在另一个数组中的数字。
这样做的目的是让我可以找到我的游戏中尚未占用的 Minecraft 块 ID。第一个数组是一个范围0..255
,它是最大可能的块 ID。下一个数组是已经使用的 id,它们已经列出了列表。
所以我想要某种循环来检查每个可能的块 id。当我到达我的电脑时,我会发布我所拥有的。
最简单(也是最快)的方法是将另一个数组转换为哈希,并检查那里是否存在键:
my %hash = map { $_ => 0 } @array2;
print (exists $hash{$_} ? "$_ is there\n" : "$_ is not there\n") for(0..255);
为什么不使用
$occupied_lookup[$_] = 1 for 4,5,6;
代替
@occupied_indexes = (4,5,6);
更容易和更快地占用一些东西:
$occupied_lookup[$_] = 1;
更容易和更快地制作空置的东西:
$occupied_lookup[$_] = 0;
更容易更快地检查是否有人占用:
if ($occupied_lookup[$_])
查找所有占用的索引仍然很容易:
my @occupied_indexes = grep $occupied_lookup[$_], 0..$#occupied_lookup;
(其他人建议使用哈希,但数组更快。)
两个数组之间的差异并不一定意味着您需要 for 循环或 while 等。这会打印 @allblocks 中不在 @occupiedones 中的项目。
#!usr/bin/perl
use warnings;
use strict;
my @allblocks=(0...255);
my @occupiedones=(1,2,80,255)
my %occupiedones=map{$_=>1} @occupiedones;
# the difference of two arrays
my @diff=grep(!defined $occupiedones{$_}, @allblocks);
# proof it works
print "This is in one array and not the other:\t$_\n" foreach (@diff);
这可以满足您的需求。代码中的注释解释。
#!/usr/bin/perl
use warnings;
use strict;
# Print members of @b that are not in @a.
# That is, loosely speaking, print @b minus @a.
my @a = (10, 20, 30, 40, 50);
my @b = (22, 25, 30, 40, 42);
my %a = map {$_=>1} @a;
$a{$_} or print "$_ " for @b;
print "\n";
这个想法是@a
变成散列%a
,然后用散列来控制减法。在散列中,只有键是感兴趣的;对应的值都是 just 1
,这对于这种应用程序来说是常规的(虚拟值是 Perl 实现在 C++ 中称为set的方式)。