$text = "I like apples more than oranges
"。
@words = split /" "/, $text;
foreach (@words) [1. ] {
if $words "AEIOUaeiou"/span>;
$words =~ tr/A E I O U a e i o u/d;
}
print "$words
"。
"我喜歡蘋果多于桔子 "將變成 "我喜歡蘋果比桔子多"。"I "中的 "I"、"appls "中的 "a "和 "orngs "中的 "o "將保留,因為它們是該詞的第一個字母。
這是我作為一年級學生的研究任務。我被允許提出問題并在之后參考它們。請不要吝嗇。
這是我作為一年級學生的研究作業,我可以提出問題并在以后參考它們。
uj5u.com熱心網友回復:
我知道你說你不允許使用regex,但是對于其他出現在這里的人,我會展示適當工具的使用。但是,然后我會用tr//做一些同樣有用的事情。
編程(和數學)的訣竅之一是將看起來很困難的問題分解成更容易的問題,特別是當你已經有了簡單問題的解決方案。(例如,請閱讀Parnas 分解)。
因此,問題是 "我怎樣才能洗掉所有的元音,除非它們在詞的開頭?" (在我把你的標題變得更短一些之后)。這導致了答案對單詞的思考,所以他們拆分了輸入,做了一些作業以確保他們不在第一個字符上作業,然后重新組裝了結果。
但是,另一種方式是 "我如何移除所有元音,除非它們在單詞開頭"。
但是,另一種構建問題的方式是 "我如何洗掉所有在另一個字母后面的元音?"。唯一不在另一個字母之后的字母是一個單詞的第一個字母。
在另一個字母之后出現的元音的重碼很簡單(但我在這里堅持使用ASCII,盡管它對任何Unicode字母都一樣簡單):
[a-z][aeiou] 。
這只在第一個字母后有元音的情況下匹配。現在你想把所有這些都替換為空。使用替換運算子,s//。/g標志使所有全域替換,/i使其不分大小寫:
s/[a-z][aeiou]/gi;
但是,有一個問題。它還替換了那個首字母。這很容易解決。替換中的K表示在替換中忽略模式的前面部分。在K之前的任何內容都不被替換。因此,這只替換元音:
s/[a-z]K[aeiou]/gi;
但是,也許有元音相鄰,所以扔進 量詞,表示前面的 "一個或多個":
s/[a-z]K[aeiou] //gi。
你根本不需要關心單詞。
你根本不需要關心單詞。
其他一些方法
說一個字母必須跟在另一個字母后面有一個特殊的零寬度斷言:非字邊界,B(盡管這也把數字和下劃線算作 "字母"):
s/B[aeiou] //gi。
K是在v5.10中引入的,它確實是一個漂亮的技巧,可以有一個可變寬度的lookbehind。但是,這里的lookbehind是固定寬度的:它是一個字符:
s/(?<=[a-z])[aeiou] //gi;
但是,關心的話
假設你需要單獨處理每個單詞,以滿足一些其他要求。看起來你混合了一點Python的那種代碼,如果Perl能做到這一點就好了:)。問題并沒有改變那么多,因為你可以對每個單獨的單詞做同樣的事情。foreach my $word ( split s /, $x ) {
.... # 每個詞的情況都一樣。
}
但是,這里有一個有趣的轉折?你如何把它全部放回原處?其他的解決方案只是使用一個空格,假設那是分隔符。也許應該有兩個空格,或制表符,或其他什么。split有一個特殊的 "分隔符保留模式",可以保留碎片之間的任何東西。當你在split模式中擁有捕獲值時,這些捕獲值是輸出串列的一部分:
my @words_and_separators = split /(s )/, $x。
因為你知道沒有一個分隔符會有元音,所以你可以對它們進行替換,知道它們不會改變。這意味著你可以像對待單詞一樣對待它們(也就是說,不存在特殊情況,這是你在分解問題時需要考慮的另一件事)。為了得到你的最終字串與原始間距,join在空字串上:
my $ending_string = join ''/span>, @words_and_separators;
因此,這里是所有這些可能的組合的樣子。我將在替換中加入/r標志,這樣它就會回傳修改后的副本,而不是在原始的副本上作業(不要修改控制變數!):
'' 因此,我們可以將這些內容放在一起。
my @words;
foreach my $word ( split /(s )/, $x ) {
push @words, $word =~ s/B[aeiou] /gr;
}
my $ending_string = join ''/span>, @words;
但是,那個foreach有點讓人討厭。這個串列流水線是一樣的,從下往上看這些東西更容易。每件事情都產生一個串列,流向它上面的事情。這就是我在真正的代碼中可能的表達方式:
my$ending_string =
join ''/span>。
map { s/B[aeiou] /gr } # 每個專案都在$_中
split /(s )/, $x;
現在,這里是大結局。如果我們不在空白處分割東西,而是在空白處和每個詞的第一個字母上分割呢?通過分隔符保留模式,我們知道我們只需要影響每一個其他專案,所以我們在做map時計算它們:
my $n = 0;
my $ending_string =
join ''/span>,
map { $n % 2 ? tr/aeiouAEIOU/dr : $_ }
split /((?:^|s )[a-z])/i, $x;
但是,我不會這樣寫這個技術,因為有人最終會找到我并進行報復。相反,我之前覺得很煩人的那個foreach可能會安撫憤怒的群眾:
my $n = 0;
foreach ( split /((?:^|s )[a-z])/i, $x ) {
print $n % 2 ? tr/aeiouAEIOU//dr : $_;
}
這現在記住了原始字串中的實際分隔符,而不考慮 "字 "的第一個字符,因為它不在我們要修改的元素中。
foreach中的代碼不需要使用條件運算子,? :或其他一些功能。重要的部分是跳過每一個其他元素。如果你以前沒有見過這個split模式,那就有點讓人費解了,但這就是你的那些要求。我認為修改子串的一部分也有可能讓人們在第一次閱讀時被絆倒。
我的意思是,如果他們要讓你在作業中用錯誤的方式來做,那就用一些會占用他們時間的東西來反擊。
哦,這很有趣
。我有另一個想法,因為tr//除了音譯之外,還有另一個任務。它還可以進行計數。因為它回傳替換的數量,如果你用自己替換任何東西,你會得到該東西出現的次數。你可以計算元音,例如:
my $has_vowels = $string =~ tr/aeiou/aeiou/; # 計算元音
但是,對于一個字母的字串,這意味著你有辦法判斷它是否是元音:
my $is_vowel = substr ( $string, $i, 1 ) =~ tr/aeiou/aeiou/;
你也可以知道關于前一個字符的事情:
my $is_letter = substr( $string。$i - 1, 1 ) =~ tr/a-zA-Z/a-zA-Z/;
把這些放在一起,你就可以查看任何位置,并知道它是否是一個元音,緊隨一個字母。如果是,你就跳過那個字母。否則,你將該字母添加到輸出中:
use v5.10;
$x = "我喜歡蘋果多過橙子 oooooranges
"。
my $output = substr $x, 0, 1; # avoid the-1 trap (end of string!)
for( my $i = 1; $i < length $x; $i ) {
if( substr( $x, $i, 1 ) =~ tr/aeiou/aeiou/ ) { #為元音 #為元音
next if substr( $x。$i - 1, 1 ) =~ tr/a-zA-Z/a-zA-Z/;
}
$output .= substr $x, $i, 1;
}
say $output;
這有一個有趣的后果,那就是使用推薦的運算子,但完全繞過了意圖。但是,這也是對tr//的正確和預期的使用。
uj5u.com熱心網友回復:
看來在接受這樣的挑戰之前,你需要把多花點功夫學習Perl。你的例子中包含了很多根本不是有效的Perl的代碼。
$x = "I like apples more than oranges
"; #原來的句子。
foreach $i in @x[1. ] {
你把你的文本分配給標量變數$x,但又試圖使用陣列變數@x。在Perl中,這是兩個完全獨立的變數,沒有任何聯系。另外,在Perl中,范圍運算子(...)需要兩端的值。
如果你有一個叫做@x的陣列(你沒有,你有一個標量),那么你可以用foreach $i (@x)
if $i "AEIOUaeiou";
我不確定你在這里想做什么。我想我能看到的最近的有用的Perl運算式應該是這樣的:
if ($i =~ /^[AEIOUaeiou]$/)
這將測驗$i是否是一個元音。但這是一個重構函式,所以你不允許使用它。
很明顯,我可以用一個regex來解決這個問題,但是由于那些regex是被禁止的,我在下面的代碼中使用了一些略微晦澀的Perl特性(這樣你的老師就不會相信你的解決方案是這樣的,如果你只是剪切和粘貼的話):
#!/usr/bin/perl
use strict;
使用警告。
use feature 'say';
my $text = "I like apples more than oranges
"。
# 將字串分割成一個單詞陣列。
my @words = split s /, $text;
# For each word...
for (@words) {
# 獲取一個省略了第一個字符的子串。
# 并使用tr///從該子串中洗掉元音。
substr($_, 1) =~ tr/AEOUaeiou/d;
}
# join the array back together
$text = join ' '/span>, @words;
say $text。
更新:哦,注意我使用了tr/AEIUOaeiou/d,而你使用了tr/A E I O U a e i o u/d。它在這里可能不會有任何區別(取決于你的方法--但你可能會將它應用于不包含空格的字串),但好的做法是只包括你想洗掉的字符。
uj5u.com熱心網友回復:
我們可以從輸入字串的末尾開始,洗掉任何前面沒有空格的元音。我們從右到左,所以我們不需要在每次洗掉后調整位置。我們不需要檢查第一個字母,它不應該被洗掉。要洗掉一個元音,我們可以在原始字串的substr上使用tr//d。
for my $i (reverse 1 . .length $x) {
substr($x, $i, 1) =~ tr/aeiouAEIOU/d
if substr($x, $i - 1, 1) ne ' '/span>。
uj5u.com熱心網友回復:
首先,你的if陳述句是錯誤的。 其次,這不是一個Perl代碼。 這里有一段可以作業的代碼,但有一個更好的方法可以做到這一點
。my $x = "I like apples more than oranges
"。
my $new = "";
my @arr;
foreach my $word (split(', $x)) {
@arr = split(''/span>, $word)。
foreach (my $i; $i<scalar @arr; $i ){
if ($i == 0) {
$new .= $arr[$i];
}
elsif (index("AEIOUaeiou"/span>, $arr[$i]) == -1) {
$new .= $arr[$i];
}
}
$new .= " "/span>;
}
print "$new
"。
在這里,我正在分割字串以獲得一個陣列,然后我正在檢查給定的字符是否是元音,如果不是,我正在將其追加到一個新的字串中。
總是包括
use strict;
use warnings;
在你的代碼上面。
uj5u.com熱心網友回復:
很明顯,這是一個關于lvalues的練習。很明顯。毋庸置疑!
#!/usr/bin/env perl
# any old perl will do[/span].
使用 5.010。
use strict;
使用警告。
# This is not idomatic nor fantastic code. 白癡?
$_='I am yclept Azure-Orange, queueing to close a query. 你怎么樣?"。
# My little paws typed "local pos" and got.
# "匹配位置的無用本地化":()
# 所以一個繁忙的$b保持/恢復了這個值。
while (/./g) {
substr($_,$b=pos,/g & & -$b pos)
# 建議使用tr是詩意的,不是實用的,。
# ~ tr有時是y,y有時是元音。
=~ y/aeiouAEIOU/d。
pos=$b。
}
say; pos=$b; }
# "say "是最后一個詞。。
是否有禁止使用s//替換的規定,或者禁止使用所有的regex?出于某種原因,我認為匹配是可以的,只是不能使用替換。如果匹配是可以的,我有一個想法,通過模式匹配的副作用去除$b來 "改善 "這個問題。我想看看它是否可行。如果不行的話,用index和變數來取代//和pos應該是很容易的,盡管在這種情況下,詞的邊界的定義過于簡化了。
(編輯)在這里,它是一個更清晰的,沒有一個regex
。my $text="YO you are the one! 唯一的人--詢問雙倍空格的問題。
不幸的是換行..."。
for (my $end=length $text;
$end > 0 && (my $start = rindex $text,' ', $end);
$end = $start-1) {
# y是一個美麗的字母,用它來表達元音是一種詩意。。
substr($text,2 $start,$end-$start) =~ y/aeiouUOIEA/d;
}
say $text。
也許更多狡猾的人將會用vec、unpack、open、fork取得成功?
你可以通過以下方式了解其中的一些技術
perldoc -f substr
perldoc -f posperldoc re
至于我自己的實作者筆記,最不重要的是結束時沒有標點符號,所以后面什么都不能去
。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/328599.html
標籤:
