0

I've been trying and trying with this one, but it just doesn't seem to click. If I have an array with let's say 6 numbers:

@a = (1,2,3,4,5,6)
  1. How do I get every second index ( 2, 4, 6) in this case?

  2. how do I compute the difference of every two elements, so the output here would be:

1 1 1 (because 2-1 =1 and 4-3 =1 and so on..)

1
  • 1
    Perhaps you would get a more valuable answer if you posted your attempts. Then we could tell you why your attempts failed. As well as present a working solution. Commented Jul 25, 2014 at 11:30

7 Answers 7

3

Note: don't ever use $a or $b, they're special (sort uses them) ... it's generally better to give your variables a descriptive name, name it as to what's in there rather than what type of variable it is.

for ( my $index = 0; $index < scalar( @pairs ); $index += 2 ) {
  my $first = $pairs[ $index + 0 ];
  my $second = $pairs[ $index + 1 ];
  my $pair = $index / 2;
  my $difference = $second - $first;
  print "the difference of pair $pair is $difference\n";
}
Sign up to request clarification or add additional context in comments.

1 Comment

If @pairs isn't used after the loop, a destructive while loop is much clearer: while (@pairs) { my $x = shift(@pairs); my $y = shift(@pairs); my $diff = $y - $x; ... }
1

I think you should post your earlier attempts. In my opinion, the best way to learn is to learn from your mistakes, not being presented a correct solution.

For this problem, I think I would use a C-style for-loop for the first part, simply because it is straightforward, and can easily be tweaked if some new requirement comes up.

The second problem can easily be solved using a regular Perl-style for-loop.

use strict;
use warnings;   # always use these two pragmas

my @nums = 1..6; 
my @idx;
for (my $n = 0; $n <= $#nums; $n += 2) {    # loop from 0 to max index, step 2
    push @idx, $n;                          # store number in @idx
}
print "Indexes: @idx\n"; 

my @diff;
for my $n (0 .. $#nums - 1) {               # loop from 0 to max index minus 1
    push @diff, $nums[$n + 1] - $nums[$n];  # store diff in @diff
}
print "Diff: @diff\n";

Output:

Indexes: 0 2 4
Diff: 1 1 1 1 1

Comments

1

Try this:

use strict;
use warnings;

my $index = 1;
my @a = (1,2,3,4,5,6);
for (@a) {
    if ($index % 2 == 0) {
        my $diff = $_ - $a[$index-2];
        print $diff;
    }
$index++;
}

4 Comments

You should not use map as a for-loop. You should use for for that. Also, you should use proper variable names and make use of spaces and indentation, this is not code golf.
I fixed your question for you. Notable in this rendition is that you do not need the $diff variable, you can just print the subtraction. Also, that it would be much easier to just loop over the indexes.
I appreciate that, but you left a bug in my $diff = $_ - $a[$c-2]; which i have fixed :)
Wouldn't want you to think I would do all the work for you.. :D
1

You likely want to use the new List::Util pair functions.

For your first question:

use List::Util 'pairvalues';

my @seconds = pairvalues @list;  # yields (2, 4, 6)

For your second question:

use List::Util 'pairmap';

my @diffs = pairmap { $b-$a } @list;  # yields (1, 1, 1)

Comments

0

You can use map:

my @a = 1 .. 6;
print join ' ', 'Every second:', map $a[ 1 + $_ * 2 ], 0 .. $#a / 2;
print "\n";
print join ' ', 'Differences:', map $a[ 1 + $_ * 2 ] - $a[ $_ * 2 ], 0 .. $#a / 2;
print "\n";

4 Comments

While I do agree map is awesome, it's not necessarily what I'd suggest to a beginner.
@Leeft map isn't really that special, its a loop that returns a list at the end, that is all.
Thank you, will try to grasp the idea of map.
@user3523464: It just takes a list, runs the given code/expression on each member, and returns a list of the results.
0

First: Don't use variables a and b. $a and $b are special variables used in sorting. Just be a bit more descriptive of your variables (even if it's merely @my_array) and you should be fine.

You can loop through your array any which way you like. However, I prefer to use a while loop instead of the thee part for because the three part for loop is a bit misleading. It is a while loop in disguise and the promised indexing of the loop can be misleading.

#! /usr/bin/env perl
use warnings;
use strict;
use feature qw(say);

my @array = qw( 1 2 3 4 5 6 );
my $index = 1;      # Remember Perl indexes start at zero!
while ( $index <= $#array ) {
    say "Item is $array[$index]";
    say "The difference is " . ($array[$index] - $array[$index-1]);
    $index += 2;
}

You said every second element. Indexes of arrays start at 0, so you want the odd number elements. Most of the answers use map which is a very nice little command, but does an awful lot in a single line which can make it confusing for a beginner. Plus, I don't think the Perldoc on it is very clear. There should be more simple examples.

The say is a newer version of print. However say always adds a \n at the end. You should always use strict; and use warnings;. These will catch about 90% of your programming bugs.

The qw( ... ) is a quick way to make an array. Each word becomes an array element. You don't need quotes or commas.

Comments

0
#!/usr/bin/perl
use strict;
use warnings;

my @ar = (1, 2, 3, 4, 5, 6);

# 1. How do I get every second index ( 2, 4, 6) in this case?
my @even = map { $_ & 1 ? $ar[$_] : () } 0 .. $#ar;

# 2. how do I compute the difference of every two elements?
my (@c, @diff) = @ar;
push @diff, -1 * (shift(@c) - shift(@c)) while @c;

use Data::Dumper;
print Dumper \@even;
print Dumper \@diff;

1;

__END__
$VAR1 = [
          2,
          4,
          6
        ];
$VAR1 = [
          1,
          1,
          1
        ];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.