2016-04-11 6 views
7

Setの主な利点はユニークな要素を維持しているようです。 Arrayは様々な機能や操作を持っているのでしかし、それは簡単に、私が出会ったとArrayルビーセットの利点

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を使用すべきですか?

Setを比較するリンクがたくさんありますが、私はSetの重要なアプリケーションに出くわしていません。

+1

これは幅広い質問であり、意見で大きく定義されています。すでに述べたように、すべてがユースケースに依存します。あなたがセットのユースケースをほとんど見つけていないという事実は、これがすべて同じであるということを意味しません。 –

+0

私はプログラミングとルビーが初めてです。私が「少数のユースケース」と言及したとき、私は露出の欠如を意味していました。私は、他人がどのようにそれを実装(適用)しているかを見て、セットとそのアプリケーションをよりよく理解することを望んでいました。ありがとう。 – Prashanth

+0

私は、Prashanthを理解します。それを個人的に服用しないでください。私はちょうどこれが非常に個人的であり、簡単に一般化できないことを意味しました。 –

答えて

8

もちろん、Setで何でもできますが、Arrayで行う方法があります。 Setを使用する利点は、Hashに基づいて実装されているため、ほとんどの操作はO(1)の複雑さですが、Arrayを使用するとO(n)になります。

例は以下のとおりです。

Set.new([1, 2, 3]).include?(2) # O(1) complexity 
[1, 2, 3].include?(2) # O(n) complexity 
+0

a)プルーフリンクと、b)「最も」の操作のより具体的なリストを持つことは素晴らしいことです。 – mudasobwa

1

まあ、技術的にはあなたがルビーArraysSetsを使用して同じ結果を得ることができます。しかし、RubyのModulesClassesについても同じことが言えます。あなたは両方の変数とメソッドを持つことができますが、それらは異なる目的を果たし、他の人がコードを読むときには、意思決定を理解することなくその意味を持ちます。

SetsArraysの場合は同じです。 と同じ結果を得ることができますが、変数をセットすることでビジネスロジックに関する追加情報を伝えます(内容は一意でなければなりません)。基本的に、それらは異なるデータ構造です。異なるデータ構造を持つ理由があります。あなたが.subset?.superset?.intersect?など新規参入がarray | array操作が何をするか推測されるだろうなどの操作を行う際に

は第二に、セットであなたのコードは、より読みやすいですが、セットで、それはすべてそこにあります。読みやすくである1を参照してください。第三に

([1, 2, 3] & [2, 3]).empty?   # => false 
Set[1, 2, 3].intersect? Set[2, 3] # => true 

、セットとの交点の操作がおそらく事前に最適化され、より高速に実行可能です。

5

これら2つのクラスが異なるデータ構造を定義:

アレイ

  • 要素
  • を重複していることができる注文
  • 要素を検索するため
  • に反復することができる保持付加、遅いです要素を取得し、位置から要素を取得することが高速です
  • uniquen要素のESSは遅い

設定

ある
  • は(理論的背景:https://en.wikipedia.org/wiki/Partially_ordered_set)注文する必要はありません
  • 重複していることができない要素要素の存在を探し
  • が速く、追加されます要素が高速です
  • デザインによって一意性が指定されています

セットは、実際に数学の概念から取られています。https://en.wikipedia.org/wiki/Set_(mathematics)ドキュメントに言ったようにRubyは、ストレージの利用ハッシュを設定する内部の内側

:あなたは以下の点に注意しなければならないので、

セット、ストレージとしてハッシュを使用しています。

要素の等価性は、Object#eqlによって決定されますか?オブジェクト#ハッシュ セットは、格納されている間、各要素のIDが に変更されないと仮定します。セットの要素を変更すると、 セットが信頼できない状態になります。文字列を格納するときは、元の文字列 がすでにフリーズされていない限り、文字列のフリーズコピーが格納されます( )。

コードを調べると、内部的にはユーザー指定のオブジェクトをキーとして、ブール値を値として(正確にはオブジェクトが追加されたときにtrue)ハッシュとして格納されます。

なぜセットを使用する必要がありますか?一意性を強要し、順序を必要としない場合は、セットが最善の選択です。一意性を本当に気にせず、順序付けが重要な場合は、Arrayを選択します。それ以外の場合は

- あなたはarbitrally決定する必要があります。)明白な理由のために

3

、ここでは他の回答を参照してください。 performanseの理由 :

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) 

理由を与える:MRIのRuby 1.9.3でこの小さなベンチマークの結果を参照してください。