简体   繁体   中英

Implicit loop in Perl

I'm trying to learn Perl, and I was wondering if there was a better equivalent to map() in the following code to generate a list of four integers (fake IP addresses):

map(int(rand(155) + 100), (0,0,0,0))

In Python I would do

[int(random.randrange(100, 255)) for _ in range(4)]

Although I'm fairly certain there is a better way to do that as well.

An IPv4 address is just a 32-bit integer, so I'd use

unpack('C4', pack('N' int(rand(2**32))))

(This doesn't limit each octet to 100..255, but doing so makes no sense anyway.)

Be warned that the rand of some systems have less than 32-bits of entropy

>perl -V:randbits
randbits='15';

On those systems, it will be impossible for your code to return some IP addresses (no matter what technique you use) if you use rand . In the system in the example, only 32,768 of the 4,294,967,296 addresses can be returned by rand .

Libraries on CPAN provide random number generators with more entropy.

我通常只是这样做:

map 100 + int rand 155, 1..4

Another notation, similar to your Python example, could be:

# assign each random octet to a list.
my @list;
push @list, int(rand(155) + 100) for (1 .. 4);

Usually questioners are using a for(each) translation approach and ask if there is a more elegant way, upon which map is suggested. My preference would be to stick to your map approach but instead of processing a list of four 0's, use the range 1 .. 4 exactly as ysth has shown, it is clearer what the code is doing this way.

I'll try to convert this based on what I think your Python code is doing.

my @ip = qw(0 0 0 0);   #create 4 member array
foreach my $number(@ip) {
    $number += int( rand(155) + 100 );
}
print "Your IP array is currently '@ip'\n";

my $ip_joined = join '.', @ip;     #create period separated string from the array
print "Your joined IP string is $ip_joined\n";

If you're really trying to minimize the number of the lines for some reason, you could trim that down to a single line foreach loop by taking out some of the pretty white space:

my @ip = qw(0 0 0 0);   #create 4 member array
foreach my $number(@ip) { $number += int(rand(155) + 100) }

Looking at it that way, it really does look like a map loop:

my @ip = qw(0 0 0 0);   #create 4 member array
@ip = map { int(rand(155) + 100) } @ip;

Also, the { } of map can be replaced with a simple comma between the map expression and the list it applies to:

my @ip = qw(0 0 0 0);   #create 4 member array
@ip = map int(rand(155) + 100), @ip;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM