Home > Mobile >  How to avoid line insert to the file if the line is already present in the file?
How to avoid line insert to the file if the line is already present in the file?

Time:12-02

How should the check be made so that there are no line duplicates in the file

open ( FILE, ">newfile");
for( $a = 1; $a < 20; $a = $a   1 ) {
    my $random_number = 1  int rand(10);;
    # check to avoid inserting the line if the line is already present in the file
    print FILE "Random number is $random_number \n";
}

close(FILE);

CodePudding user response:

Enter each line into a hash as well, what makes it easy and efficient to later check for it

use warnings;
use strict;
use feature 'say';

my $filename = shift or die "Usage: $0 filename\n";

open my $fh, '>', $filename or die "Can't open $filename: $!";

my %existing_lines;

for my $i (1..19) 
{ 
    my $random_number = 1   int rand(10);

    # Check to avoid inserting the line if it is already in the file
    if (not exists $existing_lines{$random_number}) { 
        say $fh "Random number is $random_number";
        $existing_lines{$random_number} = 1;
    }   
}
close $fh;

This assumes that the intent in the question is to not repeat that number.

But if it is indeed the whole line (sentence) to be avoided then use that for the key

for my $i (1..19) 
{ 
    my $random_number = 1   int rand(10);
    my $line = "Random number is $random_number";

    # Check to avoid inserting the line if it is already in the file
    if (not exists $existing_lines{$line}) { 
        say $fh $line;
        $existing_lines{$line} = 1;
    }   
}

Notes and literature

  • Lexical filehandles (my $fh) are much better than globs (FILE), and the three-argument open is better. See the quide perlopentut and reference open

  • Always check the open call (or die... above). It can and does fail -- quietly

  • The C-style for loop is very rarely needed while the usual foreach (with synonym for) is much nicer to use; see it in perlsyn. The .. is the range operator

  • Always declare variables with my, and force that with strict pragma; always use warnings

  • If the filehandle refers to pipe-open (not the case here) always check its close

  • See perlintro for a general overview and for hashes; for more about Perl's data types see perldata. Keep in mind for later the notion of complex data structures, perldsc

CodePudding user response:

It seems like what you are asking is how to randomize the order of the numbers 1 to 20. I.e. no duplicates, random order. That can be easily done with a Schwartzian transform. For example:

perl -le'print for map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [$_, rand()] } 1..20'
6
7
16
14
5
20
3
13
19
17
4
8
15
10
9
11
18
1
2
12

In this case, reading from the end and backwards, we create a list of numbers 1 .. 20, we feed that into a map statement which turns each number into an array-ref, containing the number, and a random number. Then we feed that list of array refs to a sort, where we sort numerically on the second argument in the array ref: the random number (hence creating a random order). Then we transform the array ref back into a simple number with another map statement. Finally we print the list using a for loop.

So in your case, the code would look something like:

print "Random number is: $_\n" for      # print each number
    map { $_>[0] }                      # restore to a number
    sort { $a->[1] <=> $b->[1] }        # sort the list on the random number
    map { [ $_, rand() ] }              # create array ref with random number as index
    1 .. 20;                            # create list of numbers to randomize order of

Then you can use the program like below to redirect output to a file:

$ perl numbers.pl > newfile.txt

CodePudding user response:

return false will do the trick.

Because you cannot generate 20 distinct numbers in the range [1, 10].

  • Related