⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch17_06.htm

📁 by Randal L. Schwartz and Tom Phoenix ISBN 0-596-00132-0 Third Edition, published July 2001. (See
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<html><head><title>Slices (Learning Perl, 3rd Edition)</title><link rel="stylesheet" type="text/css" href="../style/style1.css" /><meta name="DC.Creator" content="Randal L. Schwartz and Tom Phoenix" /><meta name="DC.Format" content="text/xml" scheme="MIME" /><meta name="DC.Language" content="en-US" /><meta name="DC.Publisher" content="O'Reilly &amp; Associates, Inc." /><meta name="DC.Source" scheme="ISBN" content="0596001320L" /><meta name="DC.Subject.Keyword" content="stuff" /><meta name="DC.Title" content="Learning Perl, 3rd Edition" /><meta name="DC.Type" content="Text.Monograph" /></head><body bgcolor="#ffffff"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Learning Perl, 3rd Edition" /><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch17_05.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228"><a href="index.htm"></a></td><td align="right" valign="top" width="228"><a href="ch17_07.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr></table></div><h2 class="sect1">17.6. Slices</h2><p><a name="INDEX-1121" />It oftenhappens that we need to work with only a few elements from a givenlist. For example, the Bedrock Library keeps information about theirpatrons in a large file.<a href="#FOOTNOTE-370">[370]</a> Eachline in the file describes one patron with six colon-separatedfields: a person's name, library card number, home address,home phone number, work phone number, and number of items currentlychecked out. A little bit of the file looks something like this:</p><blockquote class="footnote"> <a name="FOOTNOTE-370" /><p>[370]It should really be afull-featured database rather than a flat file. They plan to upgradetheir system, right after the next Ice Age.</p> </blockquote><blockquote><pre class="code">fred flintstone:2168:301 Cobblestone Way:555-1212:555-2121:3barney rubble:709918:3128 Granite Blvd:555-3333:555-3438:0</pre></blockquote><p>One of the library's applications needs only the card numbersand number of items checked out; it doesn't use any of theother data. It could use code something like this to get only thefields it needs:</p><blockquote><pre class="code">while (&lt;FILE&gt;) {  chomp;  my @items = split /:/;  my($card_num, $count) = ($items[1], $items[5]);  ...  # now work with those two variables}</pre></blockquote><p>But the array <tt class="literal">@items</tt> isn't needed foranything else; it seems like a waste.<a href="#FOOTNOTE-371">[371]</a>Maybe it would be better to assign the result of<tt class="literal">split</tt><a name="INDEX-1122" /> to a list of scalars, like this:</p><blockquote class="footnote"> <a name="FOOTNOTE-371" /><p>[371]It's notmuch of a waste, really. But stay with us. All of these techniquesare used by programmers who don't understand slices, soit's worthwhile to see all of them here.</p> </blockquote><blockquote><pre class="code">my($name, $card_num, $addr, $home, $work, $count) = split /:/;</pre></blockquote><p>Well, that avoids the unneeded array<tt class="literal">@items</tt> -- but now we have four scalar variablesthat we didn't really need. For this situation, some peopleused to make up a number of dummy variable names, like<tt class="literal">$dummy_1</tt>, that showed that they reallydidn't care about that element from the<tt class="literal">split</tt>. But Larry thought that that was too muchtrouble, so he added a special use of<tt class="literal">undef</tt><a name="INDEX-1123" />. Ifan item in a list being assigned to is <tt class="literal">undef</tt>, thatmeans simply to ignore the corresponding element of the source list:</p><blockquote><pre class="code">my(undef, $card_num, undef, undef, undef, $count) = split /:/;</pre></blockquote><p>Is this any better? Well, it has an advantage that there aren'tany unneeded variables. But it has the disadvantage that you have tocount <tt class="literal">undef</tt>s to tell which element is<tt class="literal">$count</tt>. And this becomes quite unwieldy if thereare more elements in the list. For example, some people who wantedjust the mtime value from <tt class="literal">stat</tt> were writing codelike this:</p><blockquote><pre class="code">my(undef, undef, undef, undef, undef, undef, undef,   undef, undef, $mtime) = stat $some_file;</pre></blockquote><p>If you use the wrong number of <tt class="literal">undef</tt>s,you'll get the atime or ctime by mistake, and that's atough one to debug. There's a better way: Perl can index into alist as if it were an array. This is a <em class="firstterm">listslice</em>. Here, since the mtime is item <tt class="literal">9</tt>in the list returned by <tt class="literal">stat</tt>,<a href="#FOOTNOTE-372">[372]</a> we canget it with a subscript:</p><blockquote class="footnote"><a name="FOOTNOTE-372" /><p>[372]It's the tenth item, but the index number is<tt class="literal">9</tt>, since the first item is at index<tt class="literal">0</tt>. This is the same kind of zero-based indexingthat we've used already with arrays.</p> </blockquote><blockquote><pre class="code">my $mtime = (stat $some_file)[9];</pre></blockquote><p>Those parentheses are required around the list of items (in thiscase, the return value from <tt class="literal">stat</tt>). If you wrote itlike this, it wouldn't work:</p><blockquote><pre class="code">my $mtime = stat($some_file)[9];  # Syntax error!</pre></blockquote><p>A list slice has to have a subscript expression in square bracketsafter a list in parentheses. The parentheses holding the arguments toa function call don't count.</p><p>Going back to the Bedrock Library, the list we're working withis the return value from <tt class="literal">split</tt>. We can now use aslice to pull out item <tt class="literal">1</tt> and item<tt class="literal">5</tt> with subscripts:</p><blockquote><pre class="code">my $card_num = (split /:/)[1];my $count = (split /:/)[5];</pre></blockquote><p>Using a scalar-context slice like this (pulling just a single elementfrom the list) isn't bad, but it would be more efficient andsimpler if we didn't have to do the <tt class="literal">split</tt>twice. So let's not do it twice; let's get both values atonce by using a list slice in list context:</p><blockquote><pre class="code">my($card_num, $count) = (split /:/)[1, 5];</pre></blockquote><p>The indices pull out element <tt class="literal">1</tt> and element<tt class="literal">5</tt> from the list, returning those as a two-elementlist. When that's assigned to the two <tt class="literal">my</tt>variables, we get exactly what we wanted. We do the<tt class="literal">slice</tt> just once, and we set the two variables witha simple notation.</p><p>A slice is often the simplest way to pull a few items from a list.Here, we can pull just the first and last items from a list, usingthe fact that index <tt class="literal">-1</tt> means the lastelement:<a href="#FOOTNOTE-373">[373]</a></p><blockquote class="footnote"> <a name="FOOTNOTE-373" /><p>[373]Sorting a list merely to find the extremeelements isn't likely to be the most efficient way. ButPerl's sort is fast enough that this is generally acceptable,as long as the list doesn't have more than a few hundredelements.</p> </blockquote><blockquote><pre class="code">my($first, $last) = (sort @names)[0, -1];</pre></blockquote><p>The subscripts of a slice may be in any order and may even repeatvalues. This example pulls five items from a list of ten:</p><blockquote><pre class="code">my @names = qw{ zero one two three four five six seven eight nine };my @numbers = ( @names )[ 9, 0, 2, 1, 0 ];print "Bedrock @numbers\n";  # says Bedrock nine zero two one zero</pre></blockquote><a name="lperl3-CHP-17-SECT-6.1" /><div class="sect2"><h3 class="sect2">17.6.1. Array Slice</h3><p>That previous example could be made even simpler. When slicingelements from an<a name="INDEX-1124" />array (as opposed to a list), theparentheses aren't needed. So we could have done the slice likethis:</p><blockquote><pre class="code">my @numbers = @names[ 9, 0, 2, 1, 0 ];</pre></blockquote><p>This isn't merely a matter of omitting the parentheses; this isactually a different notation for accessing array elements: an<em class="firstterm">array slice</em>. Earlier (in <a href="ch03_01.htm">Chapter 3, "Lists and Arrays "</a>), we said that the at-sign on<tt class="literal">@names</tt> meant "all of the elements."

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -