Arrays ruby中Set的优点
Arrays ruby中Set的优点,arrays,ruby,hash,set,Arrays,Ruby,Hash,Set,Set的主要优点似乎是维护独特的元素。但这可以在数组中轻松实现 array = [2,3,4] array | [2,5,6] # => [2,3,4,5,6] 我遇到的唯一不同的特性(可以应用于少数用例)是 set1 = [1,2,3].to_set set2 = [2,1,3].to_set set1 == set2 # => true [1,2,3] == [2,1,3] # => false 由于数组具有与之相关的各种功能和操作,因此何时以及为什么要使用设置 有很多
Set
的主要优点似乎是维护独特的元素。但这可以在数组中轻松实现
array = [2,3,4]
array | [2,5,6] # => [2,3,4,5,6]
我遇到的唯一不同的特性(可以应用于少数用例)是
set1 = [1,2,3].to_set
set2 = [2,1,3].to_set
set1 == set2 # => true
[1,2,3] == [2,1,3] # => false
由于数组
具有与之相关的各种功能和操作,因此何时以及为什么要使用设置
有很多链接可以比较Array
和Set
,但我还没有遇到Set
的重要应用当然,无论你用Set
做什么,都有一种方法可以用Array
来做。使用集合
的优点是,由于它是基于散列
实现的,因此对它的大多数操作都是O(1)复杂度,而使用数组
进行操作可以是O(n)
例如:
Set.new([1, 2, 3]).include?(2) # O(1) complexity
[1, 2, 3].include?(2) # O(n) complexity
从技术上讲,使用Ruby数组和集合可以获得相同的结果。但是,Ruby的模块和类也是如此。变量和方法可以同时存在,但它们的用途不同,当其他人阅读代码时,他/她将在不试图理解您的设计决策的情况下获得这一意义
我想集合
和数组
的情况是一样的。您可以使用数组实现相同的结果,但是使用集合,您的变量可以传递有关业务逻辑的附加信息(内容必须是唯一的)。基本上,它们是不同的数据结构。我们有不同的数据结构是有原因的
其次,当您执行诸如.subset?
、.superset?
、.intersect?
等操作时,使用集合时,您的代码更具可读性。新加入的用户可能会猜测数组
操作的功能,但使用集合时,它们都在那里。查看哪一个更具可读性:
([1, 2, 3] & [2, 3]).empty? # => false
Set[1, 2, 3].intersect? Set[2, 3] # => true
第三,与集合的交叉操作可能是预先优化的,并且可能运行得更快。这两个类定义了不同的数据结构:
阵列
- 可以有重复的元素
- 维持秩序
- 可以按顺序进行迭代
- 搜索元素很慢,追加元素和从位置获取元素很快
- 保持元素的唯一性很慢
设置
- 不能有重复的元素
- 没有排序(理论背景:)
- 查找元素存在的速度快,追加元素的速度快
- 独特性来自设计
集合实际上取自数学概念:
Ruby集合内部使用哈希进行存储,如文档中所述:
Set使用散列作为存储,因此必须注意以下几点:
元素的相等性是根据对象#eql?和
对象#散列。Set假定每个元素的标识不存在
在存储时进行更改。修改集合中的元素将呈现
服务器设置为不可靠状态。当要存储字符串时
将存储字符串的冻结副本,除非原始字符串
已经冻结了
当您查看代码时,它在内部存储为散列,用户给定的对象作为键,布尔值作为值(确切地说:添加对象时为true)
为什么要使用set?如果您想要强制执行唯一性,并且不需要任何排序,那么集合是您的最佳选择。当您不真正关心唯一性和顺序时,数组是您的选择
否则-您需要任意决定;) 关于显而易见的原因,请参见此处的其他答案。
出于性能原因,请参见MRI Ruby 1.9.3中的这个小基准测试的结果:
require 'benchmark'
require 'set'
array = (1..100000).to_a
set = array.to_set
#hash = Hash[array.map {|x| [x, nil]}] #beter voor heel grote volumes mar trager
hash = Hash[*array]
Benchmark.bmbm do |x|
x.report("Set.include?") { 10000.times { set.include?(99999) } }
x.report("Array.include?") { 10000.times { array.include?(99999) } }
x.report("Hash.include?") { 10000.times { hash.include?(99999) } }
end
给
Rehearsal --------------------------------------------------
Set.include? 0.000000 0.000000 0.000000 ( 0.015604)
Array.include? 37.940000 0.000000 37.940000 ( 38.651992)
Hash.include? 0.000000 0.000000 0.000000 ( 0.001000)
---------------------------------------- total: 37.940000sec
user system total real
Set.include? 0.000000 0.000000 0.000000 ( 0.002001)
Array.include? 38.157000 0.000000 38.157000 ( 38.730615)
Hash.include? 0.000000 0.000000 0.000000 ( 0.001001)
有足够的理由在可能的情况下使用Set
或Hash
。这是一个广泛的问题,观点对其有很强的定义。正如您已经说过的,这完全取决于用例。事实上,您发现集合的用例很少,这并不意味着所有的集合都是一样的。我对编程和ruby是新手。当我提到“很少使用案例”时,我的意思只是我没有暴露。我希望通过了解其他人是如何实现(应用)集合的,从而更好地理解集合及其应用。谢谢,我明白,普拉善。别把它当回事。我的意思是,这是非常个人化的,不容易推广。如果有a)一个证明链接和b)更具体的“大多数”操作列表,那就太好了。由于动态调整大小,应该分摊O(1)复杂性。太棒了。谢谢分享