检查列表中的所有元素是否在 Raku 中都是质数
Check if all elements of list are prime in Raku
my @g = (1,2,3,4);
say reduce {is-prime}, @g; # ==> gives error
say reduce {is-prime *}, @g; #==> gives error
say reduce {is-prime}, (1,2,3,4); # ==> gives error
say so is-prime @g.all; # ==> gives error
如何在 Raku 中检查列表中的所有元素是否都是素数?
您基本上是在问:此列表中是否有任何元素 不是 素数?我会写成:
say "not all prime" if @g.first: !*.is-prime;
请注意,根据 is-prime
函数,1 显然 不是 素数:
say 1.is-prime; # False
因此 first
会在您的示例中的 1 上触发,而不是在 4.[=14= 上触发]
当然有很多方法可以做到这一点。一种非常明确的方法是使用 for 循环:
for @g -> $g {
if $g.is-prime {
say $g;
}
}
或使用 grep(您可以隐式保留 $_):
@g.grep({ $_.is-prime }).say
以上都是假设你真的想过滤掉素数。当然你也可以真正检查每个数字并得到一个布尔值:
@g.map({ .is-prime }).say
使用 all
连接点:
say so all @g».is-prime; # False
上面的回答都很有帮助,但是它们无法解释为什么你的解决方案不起作用。基本上是 reduce is not going to apply a function (in your case, is-prime) to every member of a list. You want map。错误说
Calling is-prime() will never work with signature of the proto ($, *%)
因为reduce
需要一个中缀,即二元函数,或者一个有两个参数的函数;它所做的是将它们应用于第一对元素,然后应用于结果和第三个元素,依此类推。由于类似的原因,最后一条语句不起作用:您使用列表参数调用 is-prime,而不是单个参数。
这个问题很大:
say reduce {is-prime}, @g;
您创建了一个 lambda:
{ }
它唯一做的就是调用一个函数:
is-prime
虽然你没有给函数任何参数。
它只是应该猜测参数应该是什么吗?
如果您打算传入 is-prime
作为参考,您应该使用 &is-prime
而不是 {is-prime}
。
当然那还是不行。
另一个问题是 reduce
通过递归组合值来操作。
如果它一次对一个参数进行操作,它就无法做到这一点。
裸块 lambda {}
采用零个或一个参数,而不是两个或更多。
reduce
通常与 map
.
结合使用
这种情况经常发生,以至于有一个关于 MapReduce 的维基百科页面。
say ( map &is-prime, @g ==> reduce { $^a and $^b } );
# False
say ( map &is-prime, 2,3,5 ==> reduce { $^a and $^b } );
# True
我是这样写的,这样 map
就会在 reduce
之前的那一行,但这样写可能会更清楚:
say reduce {$^a and $^b}, map &is-prime, 2,3,5;
# True
reduce
带有中缀运算符非常常见,因此有一种更短的写法。
say [and] map &is-prime, 2,3,5;
# True
当然最好只找到第一个不是质数的值,然后说它的倒数。
因为即使有一个值不是质数,也意味着它们不可能都是质数。
不过你必须要小心,因为你可能认为这样的事情总是有效的:
not @g.first: !*.is-prime;
它确实适用于您给它的值,但可能并非总是如此。
first
returns Nil
如果找不到值。
not (2,3,5).first: !*.is-prime;
# not Nil === True
not (2,3,4).first: !*.is-prime;
# not 4 === False
not (2,3,0,4).first: !*.is-prime;
# not 0 === True
最后一个 returned 0
与 not
returns True
.
组合
您可以使用 defined
来解决这个问题。
not defined (2,3,0,4).first: !*.is-prime;
# False
这仅在 first
不会 return 恰好在列表中的未定义元素时有效。
(Int,Any).first: Real
# Int
defined (Int,Any).first: Real
# False
您可以通过请求索引而不是值来解决这个问题。
你当然还需要 defined
.
(Int,Any).first: :k, Real
# 0
defined (Int,Any).first: :k, Real
# True
另一种修复方法是使用 grep
.
not (2,3,0,4).grep: !*.is-prime;
# not (0,4) === False
因为 grep
总是 return 是 List
,您不必担心检查 0
或未定义的元素。
(如果 List
包含任何元素,则它是 True
,无论值是什么。)
grep
足够聪明,知道如果您强制 Bool
它可以在找到第一个值时停止。
所以它短路就像你使用 first
.
这会产生一些相当古怪的代码,其中包含这两个取反运算符。所以应该放到一个函数里面。
sub all-prime ( +@_ ) {
# return False if we find any non-prime
not @_.grep: !*.is-prime
# grep short-circuits in Bool context, so this will stop early
}
如果你给它一些奇怪的东西,这仍然会失败
all-prime 2,3,5, Date.today;
# ERROR: No such method 'is-prime' for invocant of type 'Date'
如果您关心,请添加一些错误处理。
sub all-prime ( +@_ ) {
# return Nil if there was an error
CATCH { default { return Nil }}
# return False if we find any non-prime
not @_.grep: !*.is-prime
}
all-prime 2,3,5, Date.today;
# Nil
my @g = (1,2,3,4);
say reduce {is-prime}, @g; # ==> gives error
say reduce {is-prime *}, @g; #==> gives error
say reduce {is-prime}, (1,2,3,4); # ==> gives error
say so is-prime @g.all; # ==> gives error
如何在 Raku 中检查列表中的所有元素是否都是素数?
您基本上是在问:此列表中是否有任何元素 不是 素数?我会写成:
say "not all prime" if @g.first: !*.is-prime;
请注意,根据 is-prime
函数,1 显然 不是 素数:
say 1.is-prime; # False
因此 first
会在您的示例中的 1 上触发,而不是在 4.[=14= 上触发]
当然有很多方法可以做到这一点。一种非常明确的方法是使用 for 循环:
for @g -> $g {
if $g.is-prime {
say $g;
}
}
或使用 grep(您可以隐式保留 $_):
@g.grep({ $_.is-prime }).say
以上都是假设你真的想过滤掉素数。当然你也可以真正检查每个数字并得到一个布尔值:
@g.map({ .is-prime }).say
使用 all
连接点:
say so all @g».is-prime; # False
上面的回答都很有帮助,但是它们无法解释为什么你的解决方案不起作用。基本上是 reduce is not going to apply a function (in your case, is-prime) to every member of a list. You want map。错误说
Calling is-prime() will never work with signature of the proto ($, *%)
因为reduce
需要一个中缀,即二元函数,或者一个有两个参数的函数;它所做的是将它们应用于第一对元素,然后应用于结果和第三个元素,依此类推。由于类似的原因,最后一条语句不起作用:您使用列表参数调用 is-prime,而不是单个参数。
这个问题很大:
say reduce {is-prime}, @g;
您创建了一个 lambda:
{ }
它唯一做的就是调用一个函数:
is-prime
虽然你没有给函数任何参数。
它只是应该猜测参数应该是什么吗?
如果您打算传入 is-prime
作为参考,您应该使用 &is-prime
而不是 {is-prime}
。
当然那还是不行。
另一个问题是 reduce
通过递归组合值来操作。
如果它一次对一个参数进行操作,它就无法做到这一点。
裸块 lambda {}
采用零个或一个参数,而不是两个或更多。
reduce
通常与 map
.
这种情况经常发生,以至于有一个关于 MapReduce 的维基百科页面。
say ( map &is-prime, @g ==> reduce { $^a and $^b } );
# False
say ( map &is-prime, 2,3,5 ==> reduce { $^a and $^b } );
# True
我是这样写的,这样 map
就会在 reduce
之前的那一行,但这样写可能会更清楚:
say reduce {$^a and $^b}, map &is-prime, 2,3,5;
# True
reduce
带有中缀运算符非常常见,因此有一种更短的写法。
say [and] map &is-prime, 2,3,5;
# True
当然最好只找到第一个不是质数的值,然后说它的倒数。
因为即使有一个值不是质数,也意味着它们不可能都是质数。
不过你必须要小心,因为你可能认为这样的事情总是有效的:
not @g.first: !*.is-prime;
它确实适用于您给它的值,但可能并非总是如此。
first
returns Nil
如果找不到值。
not (2,3,5).first: !*.is-prime;
# not Nil === True
not (2,3,4).first: !*.is-prime;
# not 4 === False
not (2,3,0,4).first: !*.is-prime;
# not 0 === True
最后一个 returned 0
与 not
returns True
.
您可以使用 defined
来解决这个问题。
not defined (2,3,0,4).first: !*.is-prime;
# False
这仅在 first
不会 return 恰好在列表中的未定义元素时有效。
(Int,Any).first: Real
# Int
defined (Int,Any).first: Real
# False
您可以通过请求索引而不是值来解决这个问题。
你当然还需要 defined
.
(Int,Any).first: :k, Real
# 0
defined (Int,Any).first: :k, Real
# True
另一种修复方法是使用 grep
.
not (2,3,0,4).grep: !*.is-prime;
# not (0,4) === False
因为 grep
总是 return 是 List
,您不必担心检查 0
或未定义的元素。
(如果 List
包含任何元素,则它是 True
,无论值是什么。)
grep
足够聪明,知道如果您强制 Bool
它可以在找到第一个值时停止。
所以它短路就像你使用 first
.
这会产生一些相当古怪的代码,其中包含这两个取反运算符。所以应该放到一个函数里面。
sub all-prime ( +@_ ) {
# return False if we find any non-prime
not @_.grep: !*.is-prime
# grep short-circuits in Bool context, so this will stop early
}
如果你给它一些奇怪的东西,这仍然会失败
all-prime 2,3,5, Date.today;
# ERROR: No such method 'is-prime' for invocant of type 'Date'
如果您关心,请添加一些错误处理。
sub all-prime ( +@_ ) {
# return Nil if there was an error
CATCH { default { return Nil }}
# return False if we find any non-prime
not @_.grep: !*.is-prime
}
all-prime 2,3,5, Date.today;
# Nil