Regex 检查字符串是否是一组字符的子集?(正则表达式)?
我有一个小问题,我有8个字符,例如a b c d a e f g,还有一个单词列表,例如: 妈妈,爸爸,坏,同性恋,abac 我如何检查我是否能用我的字母写这些单词? 在我的例子中,我可以写bad、abac和fag,但我不能写爸爸我没有两个D,妈妈我没有M或O 我非常确定它可以使用正则表达式来完成,但即使使用Perl中的一些函数也会很有帮助。。 提前谢谢大家!: 伪代码:Regex 检查字符串是否是一组字符的子集?(正则表达式)?,regex,string,perl,subset,Regex,String,Perl,Subset,我有一个小问题,我有8个字符,例如a b c d a e f g,还有一个单词列表,例如: 妈妈,爸爸,坏,同性恋,abac 我如何检查我是否能用我的字母写这些单词? 在我的例子中,我可以写bad、abac和fag,但我不能写爸爸我没有两个D,妈妈我没有M或O 我非常确定它可以使用正则表达式来完成,但即使使用Perl中的一些函数也会很有帮助。。 提前谢谢大家!: 伪代码: bool possible=true string[] chars= { "a", "b", "c"} foreach
bool possible=true
string[] chars= { "a", "b", "c"}
foreach word in words
{
foreach char in word.chars
{
possible=possible && chars.contains(char)
}
}
伪代码:
bool possible=true
string[] chars= { "a", "b", "c"}
foreach word in words
{
foreach char in word.chars
{
possible=possible && chars.contains(char)
}
}
这是为了证明这种可能性,而不是支持正则表达式方法。请考虑其他SANER解决方案。
第一步,您需要计算可用的字符数
然后构造您的正则表达式,因为这不是Perl代码
以输入锚的开头开始,这与列表中单个单词的字符串开头匹配:
^
根据唯一字符的数量添加以下内容:
(?!(?:[^<char>]*+<char>){<count + 1>})
例如:对于b c d a e f g,这将成为[abcdefg]+。这部分将实际使用该字符串,并确保该字符串仅包含列表中的字符
以输入锚点的结尾结束,该锚点与字符串的结尾匹配:
$
因此,对于您的示例,正则表达式将是:
^(?!(?:[^a]*+a){3})(?!(?:[^b]*+b){2})(?!(?:[^c]*+c){2})(?!(?:[^d]*+d){2})(?!(?:[^e]*+e){2})(?!(?:[^f]*+f){2})(?!(?:[^g]*+g){2})[abcdefg]+$
还必须为不区分大小写的匹配指定i标志
注意,这仅考虑英语字母表A -Z的单词匹配的情况。这里还没有考虑空格和连字符。
这是为了证明这种可能性,而不是支持正则表达式方法。请考虑其他SANER解决方案。 第一步,您需要计算可用的字符数 然后构造您的正则表达式,因为这不是Perl代码 以输入锚的开头开始,这与列表中单个单词的字符串开头匹配:^
根据唯一字符的数量添加以下内容:
(?!(?:[^<char>]*+<char>){<count + 1>})
例如:对于b c d a e f g,这将成为[abcdefg]+。这部分将实际使用该字符串,并确保该字符串仅包含列表中的字符
以输入锚点的结尾结束,该锚点与字符串的结尾匹配:
$
因此,对于您的示例,正则表达式将是:
^(?!(?:[^a]*+a){3})(?!(?:[^b]*+b){2})(?!(?:[^c]*+c){2})(?!(?:[^d]*+d){2})(?!(?:[^e]*+e){2})(?!(?:[^f]*+f){2})(?!(?:[^g]*+g){2})[abcdefg]+$
还必须为不区分大小写的匹配指定i标志
注意,这仅考虑英语字母表A -Z的单词匹配的情况。此处未考虑空格和连字符。
一些伪代码:bool possible=true
string[] chars= { "a", "b", "c"}
foreach word in words
{
foreach char in word.chars
{
possible=possible && chars.contains(char)
}
}
将可用字符按字母顺序排序
对于每个单词:
将单词的字符按字母顺序排序
对于单词的每个字符,向前搜索可用字符以查找匹配字符。注意这一点
搜索将永远不会返回到可用字符的开头,
匹配的字符被消耗。
或者更好的是,使用字符的频率计数。
对于可用字符,构造一个从字符到该字符出现计数的映射。
对每个候选单词执行相同操作,并与可用映射进行比较,如果单词映射包含可用映射没有包含的字符映射,或者单词映射中的映射值大于可用映射,则无法使用可用字符构造单词。某些伪码:
bool possible=true
string[] chars= { "a", "b", "c"}
foreach word in words
{
foreach char in word.chars
{
possible=possible && chars.contains(char)
}
}
将可用字符按字母顺序排序
对于每个单词:
将单词的字符按字母顺序排序
对于单词的每个字符,向前搜索可用字符以查找匹配字符。注意这一点
搜索将永远不会返回到可用字符的开头,
匹配的字符被消耗。
或者更好的是,使用字符的频率计数。
对于可用字符,构造一个从字符到该字符出现计数的映射。
对每个候选单词执行相同操作,并与可用映射进行比较,如果单词映射包含可用映射不包含的字符映射,或者单词映射中的映射值大于可用映射,然后,无法使用可用字符构造单词。如何将两个字符串按字母顺序排序,然后选择要插入的字符串* 在每个字母之间,如下所示:
'aabcdefg' =~ m/a.*b.*d.*/
True
'aabcdefg' =~ m/m.*m.*u.*/
False
'aabcdefg' =~ m/a.*d.*d.*/
False
将两个字符串按字母顺序排序,然后选择要插入的字符串* 在每个字母之间,如下所示:
'aabcdefg' =~ m/a.*b.*d.*/
True
'aabcdefg' =~ m/m.*m.*u.*/
False
'aabcdefg' =~ m/a.*d.*d.*/
False
最简单的方法是从要测试的单词中形成一个正则表达式 这将对可用字符列表进行排序,并通过连接这些字符形成字符串。然后将每个候选词拆分为字符,进行排序,并使用正则表达式项*作为分隔符重新连接。因此,例如,abac将转换为a.*a.*b.*c 然后,根据派生的正则表达式测试可用字符的字符串,从而确定单词的有效性
use strict;
use warnings;
my @chars = qw/ a b c d a e f g /;
my $chars = join '', sort @chars;
for my $word (qw/ mom dad bad fag abac /) {
my $re = join '.*', sort $word =~ /./g;
print "$word is ", $chars =~ /$re/ ? 'valid' : 'NOT valid', "\n";
}
输出
最简单的方法是从要测试的单词中形成一个正则表达式 这是李的分类 st是可用字符的一部分,并通过连接它们形成字符串。然后将每个候选词拆分为字符,进行排序,并使用正则表达式项*作为分隔符重新连接。因此,例如,abac将转换为a.*a.*b.*c 然后,根据派生的正则表达式测试可用字符的字符串,从而确定单词的有效性
use strict;
use warnings;
my @chars = qw/ a b c d a e f g /;
my $chars = join '', sort @chars;
for my $word (qw/ mom dad bad fag abac /) {
my $re = join '.*', sort $word =~ /./g;
print "$word is ", $chars =~ /$re/ ? 'valid' : 'NOT valid', "\n";
}
输出
下面是一个非常简单的脚本,很容易概括:
#!/usr/bin/env perl
use strict;
use warnings;
sub check_word {
my $word = shift;
my %chars;
$chars{$_}++ for @_;
$chars{$_}-- or return for split //, $word;
return 1;
}
print check_word( 'cab', qw/a b c/ ) ? "Good" : "Bad";
当然,如果字母列表每次都是相同的,那么这个函数的性能会大大提高。实际上,对于8个字符,每次复制哈希与构建新哈希的速度可能是相同的。这里有一个非常简单的脚本,很容易推广:
#!/usr/bin/env perl
use strict;
use warnings;
sub check_word {
my $word = shift;
my %chars;
$chars{$_}++ for @_;
$chars{$_}-- or return for split //, $word;
return 1;
}
print check_word( 'cab', qw/a b c/ ) ? "Good" : "Bad";
当然,如果字母列表每次都是相同的,那么这个函数的性能会大大提高。实际上,对于8个字符,每次复制哈希与构建新哈希的速度可能是相同的。可以强制正则表达式完成这项工作,但最好只进行计数。我从几个小时开始就对这项工作感到疯狂,你的意思是在性能或简单性方面更好?我认为简单的逻辑可以完成这项工作。你只处理英文字母表,对吗?是的,但我需要用一个由10个字符组成的字符串处理超过50万个单词,以检查我是否可以用10个字符创建每个单词,如果是,我必须打印每个单词。强制regex完成这项工作是可能的,但最好是只做计数。我从几个小时开始就对它发疯了,你的意思是性能更好还是更简单?我认为简单的逻辑可以完成这项工作。你只处理英文字母表,对吗?是的,但我需要用一个由10个字符组成的字符串处理超过50万个单词,以检查我是否可以用10个字符创建每个单词,如果是,我必须打印每个单词。你没有考虑计数。确切地说,双字母不被检查。。这非常简单^^你没有把计数考虑进去。确切地说,双字母是不被检查的。。这太简单了^^哦,天哪,疯狂的事!你是个怪物我马上就去试试!开始使用正则表达式的糟糕方法:@FedericoFallico:我似乎在传播糟糕的编码实践,因为我发布了一些显示可能性的东西……哦,天哪,这太疯狂了!你是个怪物我马上就去试试!开始使用正则表达式的糟糕方法:@FedericoFallico:我似乎在传播糟糕的编码实践,因为我发布了一些显示可能性的东西……难以置信,非常简单和有用,没有文字。谢谢:您在for语句中添加了500K+个单词?当然,好的,我不知道perl是否能很好地处理这些,所以不管您怎么想:难以置信,非常简单和有用,没有单词。谢谢:您在for语句中输入了500K+个单词?当然,好的,我不知道perl是否能很好地处理这个问题,所以不管您怎么想: