如何在Julia中选择与条件匹配的数组元素?

35

Julia似乎具有许多类似Matlab的功能。 我想使用谓词从数组中进行选择。 在Matlab中,我可以这样做:

>> a = 2:7 ;
>> a > 4

ans =

     0     0     0     1     1     1

>> a(a>4)

ans =

     5     6     7

我发现了一种在Julia中完成部分操作的笨拙方式:

julia> a = 2:7
2:7

julia> [int(x > 3) for x in a]
6-element Array{Any,1}:
 0
 0
 1
 1
 1
 1

(使用维基百科所称的列表推导式)。我还没有想出如何在Julia中应用这样的集合来进行选择,但可能是在错误的方向上探索。如何从一个数组中进行谓词选择?

5个回答

45

如果您使用点.进行逐元素比较,则可以使用非常类似Matlab的语法:

elementwise
julia> a = 2:7
2:7

julia> a .> 4
6-element BitArray{1}:
 false
 false
 false
  true
  true
  true

julia> a[a .> 4]
3-element Array{Int32,1}:
 5
 6
 7

如果你想更注重函数式谓词处理的话,你可以使用filter进行调用:

julia> filter(x -> x > 4, a)
3-element Array{Int32,1}:
 5
 6
 7

2
就记录而言,元素方法的速度似乎是调用过滤器的两倍。 - Peeter Joot

21

在Julia中,数组推导相对于Haskell或Python中的列表推导而言比较原始。有两种解决方案——要么使用高阶过滤函数,要么使用广播操作。

高阶过滤

filter(x -> x > 4, a)

这将使用谓词x -> x > 4(请参阅Julia手册中的匿名函数)调用filter函数。

广播和索引

a[Bool[a[i] > 4 for i = 1:length(a)]]

这将在 a 的元素和数字 4 之间执行广播比较,然后使用生成的布尔数组索引 a。可以使用广播运算符更紧凑地编写它:

a[a .> 4]

1
我有一个数组,想要根据多个条件进行过滤。例如 a > 3 && a < 5。但是当我尝试这样做时,会出现“在布尔上下文中使用非布尔值(BitArray{1})”的错误。这里的问题是什么? - lara
这个使用 filter 很好用:filter( x -> (x > 3 && x < 5), a)。更多信息请参考 http://docs.julialang.org/en/latest/stdlib/collections/?highlight=filter#Base.filter。 - Fred Schoen
1
对于数组,您必须使用位运算符a .> 3&a .<5。请注意,位与只有一个& - Fred Schoen
2
请注意,a=[1; 2; 3]; a[a.>0 & a.<1] 不会产生预期的结果!这将给出 1 2 3,因为 & 运算符具有更高的优先级。正确的解决方案是 a[(a.>0) & (a.<1)] - esel

8

我目前使用的是Julia 1.3.1版本,与早期版本相比,一些语法发生了变化。要对数组进行多条件过滤,我需要执行以下操作:

x = range(0,1,length=100)
x[(x .> 0.4) .& (x .< 0.51)] 

请注意使用'.&'作为AND运算符。

3

我希望补充一点之前的答案没有涉及到的内容。如果您想按索引值(而不是数组值)过滤数组,则可以通过a[1:end ...]实现,其中在点的位置应用广播操作符以作用于索引值。例如,要删除第三个元素,您可以编写:

a[1:end .!= 3].

这个实例还允许a[1:end .!= [2,3]]但要小心,因为a[1:end .!= []]会抛出异常。 - Daniel Pinyol

1

对于字典中的键进行过滤,以下方法适用:

mydict = Dict("key1" => 1.0, "key2" => 2.0, "a big string with a part of a string" => 3.0)
filter(x -> occursin("part of a string", string(x)), keys(mydict))

这是在Julia 1.0中REPL上的输出样式。
julia> mydict = Dict("key1" => 1.0, "key2" => 2.0, "a big string with a part of a string" => 3.0)
Dict{String,Float64} with 3 entries:
  "key2"                                 => 2.0
  "key1"                                 => 1.0
  "a big string with a part of a string" => 3.0

julia> filter(x -> occursin("part of a string", string(x)), keys(mydict))
Set(["a big string with a part of a string"])

总的来说,这是一个过滤字符串数组的好方法。

希望有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接