首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有有限数目或值的Struct元素

具有有限数目或值的Struct元素
EN

Stack Overflow用户
提问于 2020-03-20 17:35:47
回答 2查看 397关注 0票数 5

我想创建一个struct

代码语言:javascript
复制
mutable struct myStruct
    id::string
end

我确实希望id是一个字符串,但我希望它只接受3个值中的一个(例如"a""b""c")。我的想法是理论上可以加速行动。

  1. 关于提速,我说得对吗?
  2. 这有可能吗?怎么可能?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-20 21:55:57

我不知道如何让id成为一个String,同时限制它只有3个可能的值中的一个,这样编译器就可以利用它。

但是,如果离开String域是一种选择,则有几种可能性。让我们试着在这里测试其中的一些。为了示例起见,让我们假设这个id字段用于测试两个MyStruct实例之间的相等性。

这类类型的一个可能的(极简式)泛型实现如下所示,其中参数T确定用于id的类型。

代码语言:javascript
复制
mutable struct MyType{T}
    id :: T
end

# Two MyType instances are equal if their ids are equal
import Base.==
==(a::MyType{T}, b::MyType{T}) where {T} = (a.id == b.id)

现在,让我们在各种情况下对相等操作符进行基准测试。首先,使用字符串作为标识符的基本大小写:

代码语言:javascript
复制
julia> using BenchmarkTools

julia> a = MyType("apple")
MyType{String}("apple")

julia> b = MyType("banana")
MyType{String}("banana")

julia> @btime $a == $b
  4.326 ns (0 allocations: 0 bytes)
false

我们预计整数会更快,情况确实如此:

代码语言:javascript
复制
julia> a = MyType(1)
MyType{Int64}(1)

julia> b = MyType(2)
MyType{Int64}(2)

julia> @btime $a == $b
  1.882 ns (0 allocations: 0 bytes)
false

但是那样的话API可能就不那么方便了。使用枚举类型可能更易读(用户不必记住哪个值对应于"apple")。它还防止使用未预先定义的任何值,同时保持相同的性能:

代码语言:javascript
复制
julia> @enum Fruit begin
           apple
           banana
       end

julia> a = MyType(apple)
MyType{Fruit}(apple)

julia> b = MyType(banana)
MyType{Fruit}(banana)

julia> @btime $a == $b
  1.816 ns (0 allocations: 0 bytes)
false

最后一个值得考虑的选择是使用符号作为密钥,这既保留了(IMO)的可使用性,也保留了性能:

代码语言:javascript
复制
julia> a = MyType(:apple)
MyType{Symbol}(:apple)

julia> b = MyType(:banana)
MyType{Symbol}(:banana)

julia> @btime $a == $b
  1.883 ns (0 allocations: 0 bytes)
false

没有什么可以阻止任何人构建一个非法的值,比如MyStruct(:cheddar),但是它非常适合于字符串被操纵的上下文。例如,如果您在工作流中的某个位置将id作为字符串获得,则在构造MyStruct实例之前,可以轻松地将其转换为符号:

代码语言:javascript
复制
julia> id = "apple"
"apple"

julia> a = MyType(Symbol(id))
MyType{Symbol}(:apple)
票数 5
EN

Stack Overflow用户

发布于 2020-03-21 22:03:30

用朱莉娅的打字系统!不需要外部库。

代码语言:javascript
复制
abstract type Fruit end
struct Apple <: Fruit end 
struct Banana <: Fruit end
struct Coconut <: Fruit end

struct MyType{T<:Fruit}
    #could be some fields here...
end

a = MyType{Apple}()
a2 = MyType{Apple}()
b = MyType{Banana}()

这种方法有两个优点:

  • 实际上,您可以限制值的集合。
  • 比较可以在编译时执行,因此不需要花费时间。

这只是一个无与伦比的性能基准:

代码语言:javascript
复制
julia> using BenchmarkTools

julia> @btime $a == $b
  0.001 ns (0 allocations: 0 bytes)
false

julia> @btime $a == $a2
  0.001 ns (0 allocations: 0 bytes)
true

编辑

回答@Cameron Bieganek的问题

对于何时手工定义单例类型以及何时使用Enum更有意义,您有什么意见或指导吗?

我个人的意见如下:

  • 当类型值在编译时已经知道时,始终使用单例类型。
  • 每当在编译时已经知道了一小组类型(限定了一个小的联合),就使用单例时间。
  • 如果您计划根据类型实现不同的处理,那么单例类型广播将比一系列if语句更快。
  • 在设计API (您自己的Julia包)时,使用单例类型,因为您可以使用Julia的文档特性
  • 当大量在运行时生成的值(例如Strings)在运行时生成,并且您计划对它们进行比较,请使用Symbols。很好的例子是解析一个CSV文件,其中列包含标称值。
  • 在其他情况下,考虑使用Enums或Symbols --使用代码可读性作为标准。
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60778982

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档