Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

map split vs array split

by convenientstore (Pilgrim)
on Jul 30, 2007 at 22:36 UTC ( #629683=perlquestion: print w/replies, xml ) Need Help??

convenientstore has asked for the wisdom of the Perl Monks concerning the following question:

While going through tutorial, I ran into below where
author is using map command to split up the array using space and
get below results
------------foo.txt---------
hi how are you
I am fine

-----------when I run with map ---
hi how are you I am fine

I also was wondering if I could do the same w/ just array
---------- when I run with array split
@lines1 is 2

Why is this evaluating split of array to scalar?
**update** ; also, when I run below I get

i am fine
open (FH, "foo.txt") ; while (<FH>) { chomp; @lines1 = split / /, $_; } close FH; print "@lines1\n";
###### map code ############ open (FH, "foo.txt"); my @words = map { split } <FH>; close FH; print "@words\n"; ############### array split########## open (FH, "foo.txt"); my @lines = <FH>; close FH; my @lines1 = split(' ', @lines); print "\@lines1 is @lines1";

Replies are listed 'Best First'.
Re: map split vs array split
by FunkyMonk (Chancellor) on Jul 30, 2007 at 23:03 UTC
    I don't understand any of your questions, but I'll try and answer what it is I think you're asking. I beg your forgiveness if I'm wrong.

    my @words = map { split } <FH>;

    Four things are happening here...

    • <FH> is being evaluated in list context because of map. So it will return a list of lines from FH.
    • split will take each of those lines in turn, and split them by it's default, which is whitespace (it's more complicated than that, see split for the details). split returns a list of the words in a line
    • map takes each list returned by split and adds them to @words
    • @words ends up as an array of words, taken from each line in your file.

    Why is this evaluating split of array to scalar?

    Because it's within a string. Perl evaluates print "\@lines1 is @lines1" as print '@lines1 is ' . @lines1. Concatenation forces scalar context on its operands. scalar @lines1 returns the number of element in the array.

    See my reply below for the real answer to this.

    print "@lines1" is treated magically: each element of @lines1 is printed, separated by a space.

    update: ysth pointed out that what I'd written was wrong. Sorry about that.

      Hi, I am running below and getting scalar value, I thought splitting up array into array would give me list context
      ~/script/perl/temp@myserver >cat perl.map2 #!/usr/bin/perl -w use strict; open (FH, 'foo.txt'); my @lines = <FH>; close FH; my @lines1 = split(' ', @lines); print "@lines1\n"; #hi how are you #i am fine ~/script/perl/temp@myserver >./perl.map2 2
        Yet again, it's all about context:

        my @lines1 = split(' ', @lines);

        split expects a regexp and a string as arguments, which are both scalars. @lines is evaluated in scalar context, returning the number of elements it contains. So, split has nothing to split, and returns the number of elements to be assigned to @lines1.

        Simply put, you can't split arrays. The purpose of split is to split a string into a list of values. Therefore, split expects a scalar as its second argument, representing the string to split. When you pass an array, the array is evaluated in scalar context, which returns the number of elements in the array.

        If you wanted to split each of the lines, you should use a foreach loop to iterate over the values in the array and operate on them one at a time:

        foreach (@lines) { my @lines1 = split(' ', $_); # $_ is "it" -- the current element of + @lines print @lines1,"\n"; }

        Or, for another approach, you could use map:

        map { print split(' ', $_),"\n" } @lines;

        In any case, split simply does not, will not work they way you're trying to use it -- it's not supposed to.

        <radiant.matrix>
        Ramblings and references
        The Code that can be seen is not the true Code
        I haven't found a problem yet that can't be solved by a well-placed trebuchet
Re: map split vs array split
by GrandFather (Saint) on Jul 30, 2007 at 23:20 UTC

    Sigh. Read I know what I mean. Why don't you?. It has some hints for writing posts so that other people understand what you are asking and so that code you provide can be run by others with the least hassle and external dependencies.

    Where are the code samples that generate the output you show?. Why can't I see the link to the tutorial you mention?

    How often do you check the perlintro documentation when you have a problem? Something simple you can probably do at your command line is: perldoc -f <func name>. For example you could perldoc -f split to get split which would tell you that split works on an 'EXPR' (i.e. string in this case), not an array.


    DWIM is Perl's answer to Gödel
      thanks for your pointer.. and you r right.. I should read up more on these..
      ** update ** I acheived what I wanted w/ below code
      I ran into this while going through map tutorial and
      wanted to see if I can write the same code using w/out map
      But you had me realize that I need to get more through with
      basic stuff as well as writing clear questions
      thanks for all your help guys~
      use strict; open (FH, 'foo.txt'); my @lines = <FH>; my @lines1; close FH; foreach (@lines) { chomp; push my @lines1, $_; } print "@lines1\n";

        Note that chomp can act on an array so you can:

        use strict; use warnings; my $file1 = <<FILE; apple goat chocolate newyork FILE open IN, '<', \$file1; my @lines = <IN>; close IN; chomp @lines; print "@lines1\n";

        Prints:

        apple goat chocolate newyork

        DWIM is Perl's answer to Gödel
Re: map split vs array split
by ikegami (Pope) on Jul 31, 2007 at 00:09 UTC

    Seems to me like you want to get rid of the map. You can replace map with another loop.

    @array = map { EXPR } LIST;

    is functionally equivalent to

    @array = (); foreach (LIST) { push @array, EXPR; }

    So

    open (FH, "foo.txt"); my @words = map { split } <FH>; close FH; print "@words\n";

    can be written as

    open (FH, "foo.txt"); my @words; foreach (<FH>) { push @words, split; } close FH; print "@words\n";

    Since <FILE> can be used as an interator, the following is more memory-efficient:

    open (FH, "foo.txt"); my @words; while (<FH>) { push @words, split; } close FH; print "@words\n";

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://629683]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (2)
As of 2021-08-05 13:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My primary motivation for participating at PerlMonks is: (Choices in context)








    Results (44 votes). Check out past polls.

    Notices?