如何删除句子中除了第一个字母的元音之外的所有元音?

Posted

技术标签:

【中文标题】如何删除句子中除了第一个字母的元音之外的所有元音?【英文标题】:How can I remove all vowels in a sentence except for the vowel at the first letter? 【发布时间】:2021-11-11 23:27:30 【问题描述】:

这段代码具体有什么问题?我该如何纠正?

$x = "without any vowels after the first letter\n";
foreach $i (@x[1..]) 
    if ($i =~ /[AEIOUaeiou]/) 
        $x =~ tr/A E I O U a e i o u//d;
    

print "$x\n";

我尝试[1..] 排除第一个字母。如果它不起作用,我还能如何删除第一个字母?


编辑我编辑了代码,使其在语法上(大部分)正确,以传达他们明显的原始想法,除了尝试索引到在 Perl 中不正确的字符串。 (澄清这是我认为在这个问题中有用的一部分。)

【问题讨论】:

"这段代码有什么特别的问题?" --- 几乎所有的东西 -- 所写的大部分内容都不是有效的 Perl,或者实际上是任何编程语言。如果您想要/需要使用 Perl,我建议您阅读 Perl 教程,以便能够明智地使用该语言。学习基础知识并不需要很长时间。 (而且,我看不出您如何实现对实际问题的回答?) 也许你会发现有用的Modern Perl,Beginning Perl。 请阅读:How to create a Minimal, Reproducible Example, How do I ask a good question? 这是***.com/q/69218900/2766176的副本 @briandfoy 不是——他们想让每个单词中的第一个字符在该问题中不受影响,在这里他们只想留下字符串的第一个字符。其他问题的简单解决方案不在这里。 (另外,这个问题是第一位的,并不比另一个差。) 【参考方案1】:

首先,其中大部分不是 Perl,也不是任何编程语言。我建议您首先阅读您选择的 Perl 教程,然后再尝试获取特定问题的解决方案。不过,这里有一个答案,因为这个问题本身就足够引起人们的兴趣。

接下来,在 Perl 中你不能直接索引到一个字符串,所以你不能像这样跳过第一个字符。

当然,您可以将字符串中的第一个字符分开并处理其余字符(删除元音)。正则表达式的一种方法

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

my $str = shift // 'out with ALL vowels after first';

$str =~ s/.\K(.*)/ $1 =~ tr[aeiouAEIOU]dr /e;

say $str;    #-->  ot wth LL vwls ftr frst

这依赖于/e 修饰符,这使得替换端被评估为代码,因此它在那里运行一个独立的transliteration (tr),处理捕获的子字符串。

然后我们需要嵌入的tr/regex 中的/r modifier,以返回新字符串,而不是更改旧字符串——无论如何,这是不可能的无法更改$1

也可以使用tr 的正则表达式,效率较低,但有很多便利

$str =~ s/.\K(.*)/ $1 =~ s[aeiou]igr /e;

现在我们可以在该正则表达式中使用比tr 更复杂的工具;在这种情况下,它只是 i 标志,用于区分大小写-insensitive。

如果要保留的第一个字符不止一个,请将 . 更改为 .N


当然,Regex 不是强制性的。更基本的做法:split 将字符串转换为第一个字符和其余部分,然后在其余部分使用 tr

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

my $str = shift // q(out with ALL vowels after first);

my ($result, $rest) = split //, $str, 2;  # first char, rest of string

$result .= $rest =~ tr/aeiouAEIOU//dr;  # prune $rest of vowels, append to $result

say $result;

然后把它放在一个小的迷你子程序中。要更改原始字符串,而不是获取新的 ($result) 字符串,请在任何地方使用它 ($str) 而不是 $result

我不确定它如何比较效率,但它可能会很好。

为了好奇,这里只写一个声明

$str = join '', map  length > 1 ? tr/aeiouAEIOU//dr : $_   split //, $str, 2;

这特别使用了只需要跳过第一个(一个)字符的事实;只要标准确实涉及子字符串的长度,这很容易实现动态化。

更重要的是,这假设字符串的其余部分长于 1 个字符。要放弃该假设,请更改标准

use feature 'state';

$str = join '', map  
    state $chr_cnt = 0; 
    ++$chr_cnt > 1 ? tr/aeiouAEIOU//dr : $_ 
 
split //, $str, 2;

这也依赖于只保留一个字符。它使用feature 在执行过程中保持一个词法值state。

更通用的解决方案,它使用substr 的属性可以写入

substr($str, 1) =~ tr/aeiouAEIOU//d;

在这里放宽对第一个字符的限制更加简洁:只需更改 1 即可跳过更多字符。棘手的——意想不到的——部分可能是通常内置函数不能像那样写入,它们不是lvalue subroutines

【讨论】:

您好,谢谢。我们还没有被介绍过正则表达式,所以作为一年级的学生,我正在研究我们迄今为止所学到的东西。还有另一种使用 for 循环的方法吗?这就是我想要做的。 @Traveller 嗨——你展示的尝试使用tr,这是一个正则表达式风格的想法。是的,您可以通过基本方法来做到这一点——将字符串分解为字符并遍历该列表,只保留满足您条件的那些:第一个或非元音。 (但话又说回来,要检查一个字符是否不是元音,你会使用正则表达式——因为替代方案并不漂亮——五向 if 语句!)但你真的不能这样做首先学习至少一些 Perl! 这是我周一到期的作业。因此,如果没有正则表达式,我需要将其拆分为单词并稍后编写一个 if 语句。 @Traveller 一种基本方法:拆分为字符(不是“单词”),然后遍历该列表,将每个字符与元音进行比较;如果它匹配任何一个元音,它就不会被保留。如果您不能使用正则表达式,我认为您必须依次对每个元音执行eq。跳过第一个,保留。但是——你试试tr——这是否允许?如果是,则将字符串拆分为第一个字符和其余字符,并将tr 应用于其余字符,然后将它们合并回来。 @Traveller (我不知道当您显然不了解该语言时您将如何在 Perl 中做到这一点?您能在几天内掌握最基本的知识吗?有可能.)【参考方案2】:

解决问题的算法在你的问题中

如果字符串不是元音,则在字符串中添加字母 如果它是输入字符串中的第一个元音,则在字符串中添加字母
use strict;
use warnings;

my $x = "without any vowels after the first letter\n";
my($o,$count) = ('',0);

print 'IN:  ' . $x;

for ( split('',$x) ) 
    $o .= $_ unless $count != 0 and /[aeiou]/i;
    $count++ if /[aeiou]/i;


print 'OUT: ' . $o;

输出

IN:  without any vowels after the first letter
OUT: witht ny vwls ftr th frst lttr

附录:OP对问题的澄清

查看句子中的每个单词 如果单词以元音开头,则删除除第一个以外的所有元音 如果单词从无元音开始,则删除所有元音
use strict;
use warnings;
use feature 'say';

my $x = 'I like apples more than oranges';
my @o;

say 'IN:  ' . $x;

for ( split(' ', $x) ) 
    if ( /^[aeiou]/i ) 
        s/.\K(.*)/$1 =~ tr|aeiouAEIOU||dr/e;
     else 
        tr|aeiouAEIOU||d;
    
    @o = (@o,$_);


say 'OUT: ' . join(' ', @o);

输出

IN:  I like apples more than oranges
OUT: I lk appls mr thn orngs

或者在perlish风格

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

my $x = "I like apples more than oranges";

say 'IN:  ' . $x;
say 'OUT: ' . join(' ', map  s/.\K(.*)/$1 =~ tr|aeiouAEIOU||dr/e && $_  split('[ ]+', $x));

输出

IN:  I like apples more than oranges
OUT: I lk appls mr thn orngs

【讨论】:

您好,谢谢。在这一个中,所有元音都被删除。如果元音是单词中的第一个字母,我需要一个元音所在的位置。 @Traveller 你的问题有点模糊,你必须纠正它以反映你试图实现的目标。为了获得最佳结果,您必须提供一些输入和预期输出示例。 我编辑了我最初创建的代码。抱歉,如果我的问题晦涩难懂,我也对其进行了编辑 @Traveler -- 我是否理解正确:$str = 'astringing'; 将变为 $str = 'astringing';$str = 'stringing' 变为 $str = 'strngng?为清楚起见,在您的问题中添加一些示例。 它会变成'astrngng'。 "a" 将保留,因为它位于字母的开头。 “我”将消失。

以上是关于如何删除句子中除了第一个字母的元音之外的所有元音?的主要内容,如果未能解决你的问题,请参考以下文章

如何编写一个函数,将句子中每个单词开头的所有辅音字符串转换为“r”,直到它变成元音?

python统计并输出字符串中小写元音字母的个数?

Leetcode练习(Python):第345题:反转字符串中的元音字母:编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

Leetcode练习(Python):第345题:反转字符串中的元音字母:编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

c#winform 的所有控件缩写是啥

字母“L”的发音规则?