カテゴリ: Ruby 更新日: 2026/02/13

RubyのSetとHashの違いを徹底比較!初心者向けに用途と性能をガイド

SetとHashの違いを理解する:内部構造・用途・性能の観点で比較
SetとHashの違いを理解する:内部構造・用途・性能の観点で比較

先生と生徒の会話形式で理解しよう

生徒

「Rubyを勉強しているとHash(ハッシュ)とSet(セット)という言葉が出てきました。どちらもデータを集めるものみたいですが、何が違うんですか?」

先生

「鋭い視点ですね!実は、Setは内部でHashを利用して作られている、いわば兄弟のような関係なんです。」

生徒

「えっ、兄弟なんですか?じゃあ、どっちを使っても同じ結果になるんでしょうか?」

先生

「いいえ、使い道が全く違います。Hashは『意味のセット』、Setは『ダブリのない集まり』に特化しているんですよ。詳しく見ていきましょう!」

1. Hash(ハッシュ)とは?「名前と値」のペア

1. Hash(ハッシュ)とは?「名前と値」のペア
1. Hash(ハッシュ)とは?「名前と値」のペア

RubyのHash(ハッシュ)は、特定の「名前(キー)」と、それに対応する「中身(値)」をセットにして保存するデータ形式です。プログラミング未経験の方には、「国語辞典」をイメージすると分かりやすいでしょう。「単語」がキーで、その「意味」が値です。

例えば、ある人のプロフィールを作るときに、名前は「田中さん」、年齢は「25歳」といった風に、ラベルを貼って管理するのが得意です。パソコンを触ったことがない方でも、整理棚の引き出しに「靴下」「シャツ」とラベルを貼る様子を想像すれば、ハッシュの便利さが伝わるはずです。ハッシュを使えば、大量のデータの中から「名前は誰だっけ?」とラベルを頼りに一瞬でデータを取り出すことができます。


# ハッシュの作成(ラベルと値のセット)
user_profile = {
  "name" => "田中",
  "age" => 25,
  "city" => "東京"
}

puts user_profile["name"]

実行結果は以下の通りです。


田中

2. Set(セット)とは?「唯一無二」の集まり

2. Set(セット)とは?「唯一無二」の集まり
2. Set(セット)とは?「唯一無二」の集まり

一方、Set(セット)は「集合」と呼ばれ、重複した値を一切許さないデータの集まりです。Setの最大の特徴は、同じものを二度入れようとしても、コンピュータが自動的にそれを拒否してくれる点にあります。

身近な例で言えば、「出席名簿」です。同じ名前の人が二人いては困る場合や、トランプのカードが全種類揃っているか確認する場合などに適しています。ハッシュとの最大の違いは、ハッシュが「名前と値のペア」だったのに対し、セットは「値そのもの」だけをバラバラと、でも重複なく持っているという点です。RubyでSetを使うには require 'set' という一文が必要です。これは「Setという道具を使えるように準備して」という合図です。


require 'set'

# セットの作成(重複は消える)
numbers = Set.new([1, 2, 2, 3, 3, 3])

# 重複が排除された結果を表示
p numbers

実行結果は以下の通りです。


#<Set: {1, 2, 3}>

3. 内部構造の秘密:SetはHashの親戚?

3. 内部構造の秘密:SetはHashの親戚?
3. 内部構造の秘密:SetはHashの親戚?

ここが少し驚きなポイントですが、RubyのSetは、実は内部的にはHashの仕組みを利用して動いています。Hashには「キー(ラベル)は重複してはいけない」という絶対的なルールがあります。Setはこの仕組みを応用して、値をすべてHashの「キー」として保存することで、重複を防いでいるのです。つまり、SetはHashから「値」の部分を取り除いて、ラベルの管理機能だけを強化した特化型モデルと言えます。

内部で同じ技術(ハッシュテーブルと呼ばれます)を使っているため、どちらも「データを探すスピード」が極めて速いという共通の強みを持っています。配列(Array)のように端から順番に探すのではなく、一瞬で「そこにある!」と見つけ出せるのが、この二つの兄弟が優秀な理由です。専門用語では「検索性能が高い」と表現します。

4. 用途で選ぶ:ラベルが必要か、存在が重要か

4. 用途で選ぶ:ラベルが必要か、存在が重要か
4. 用途で選ぶ:ラベルが必要か、存在が重要か

「ハッシュとセット、どっちを使えばいいの?」と迷ったときは、以下の基準で選んでみましょう。プログラミングの設計において、道具選びは非常に重要です。

  • Hashを選ぶとき: 「誰の」「何の」といった関連付けが必要なとき。ユーザー設定、商品の在庫数、テストの結果表など、特定の対象に対して説明を加えたい場合です。
  • Setを選ぶとき: 「ダブりがないこと」を確認したいとき、または「その仲間に入っているか」だけを知りたいとき。既に送信済みのメールアドレス一覧や、許可されたユーザーIDのリストなどです。

例えば、ログインシステムを作るとしましょう。「ユーザーIDとパスワード」をセットで管理するならHashが正解です。一方で、「現在オンライン中のユーザーID」を重複なく管理するだけならSetの方がコードもスッキリして扱いやすくなります。

5. 性能の比較:どちらが速い?

5. 性能の比較:どちらが速い?
5. 性能の比較:どちらが速い?

性能(スピード)に関しては、HashもSetもほぼ互角です。どちらも「ハッシュ値」という特殊な計算を使ってデータの場所を特定するため、データが10個あっても、100万個あっても、探し出す時間はほとんど変わりません。これをプログラミングの専門用語で O(1)(オー・ワン) と呼びます。パソコン操作に不慣れな方は、「探し物をする時間が常に一瞬」という最高ランクの速さだと考えてください。

ただし、メモリ(パソコンの作業スペース)の消費量で見ると、Setの方が少しだけ効率的な場合があります。Hashは「名前」と「中身」の二つを覚える必要がありますが、Setは「名前(値)」だけで済むからです。とはいえ、現代のコンピュータではその差を感じることはほとんどありませんので、性能よりも「どちらが自分のやりたいことに合っているか」という使い勝手で選ぶのがベストです。

6. Set特有の便利な「集合演算」

6. Set特有の便利な「集合演算」
6. Set特有の便利な「集合演算」

Hashにはない、Setだけの強力な武器が「集合演算」です。これは複数のグループを比較して、「共通している人は誰か?」「Aグループにしかいない人は誰か?」といった計算を直感的に行う機能です。これをHashでやろうとすると、複雑なプログラムを書く必要がありますが、Setなら記号一つで解決します。


require 'set'

team_a = Set.new(["佐藤", "田中", "鈴木"])
team_b = Set.new(["田中", "高橋", "伊藤"])

# 両方のチームに所属している人(積集合)
both = team_a & team_b

# どちらかのチームに所属している人(和集合)
either = team_a | team_b

puts "両方にいる人: #{both.to_a}"

実行結果は以下の通りです。


両方にいる人: ["田中"]

このように、グループ同士の関係性を調べたいときは、迷わずSetを選びましょう。ハッシュを無理やり使って集合を扱うのは、まるでドライバーで釘を打つようなもので、非効率になってしまいます。

7. Hashにしかない機能「デフォルト値」

7. Hashにしかない機能「デフォルト値」
7. Hashにしかない機能「デフォルト値」

今度はHashの独自機能を見てみましょう。Hashは、存在しない名前の引き出しを開けようとしたときに「何を表示するか」を決めておく デフォルト値(初期値) という設定ができます。これはSetにはない機能です。

例えば、果物の数を数えるプログラムを作る際、まだリストにない果物が出てきたら「0個からスタートする」という設定ができるため、プログラムが非常に書きやすくなります。Setはあくまで「あるか・ないか」の管理なので、このようなカウント作業や細かい数値管理には向きません。


# 存在しないキーに対して「0」を返すハッシュ
counts = Hash.new(0)

counts["apple"] += 1
counts["orange"] += 1

puts counts["apple"]
puts counts["banana"] # まだ無いけどデフォルトの0が出る

実行結果は以下の通りです。


1
0

8. 初心者が間違えやすいポイント

8. 初心者が間違えやすいポイント
8. 初心者が間違えやすいポイント

最後に、よくある勘違いを整理しておきましょう。SetとHash、どちらも似たようなカッコ {} を使うことが多いため、見た目で混乱しがちです。しかし、中身が 名前: 値 となっていればHash、値, 値 となっていればSet(または配列)という違いがあります。また、Setは標準では p メソッドで表示した時に #<Set: {...}> という特殊な表示になります。これを「変な文字が出た!」と驚かなくて大丈夫です。これは「これはSetという種類のデータだよ」とRubyが教えてくれているだけなのです。

また、パソコンを使い始めたばかりの方が陥りやすいミスとして、Setを使うときに require 'set' を忘れてしまうことがあります。Rubyのプログラムは、最小限の機能で動き始めます。Setのような専門的な道具を使うときは、必ず最初に「倉庫から持ってきて!」と指示するのを忘れないようにしましょう。これができれば、あなたもデータ管理の達人への第一歩を踏み出したと言えます!

関連記事:
カテゴリの一覧へ
新着記事
New1
Ruby
Rubyプログラムの実行方法まとめ:スクリプト・REPL・Shebang・実行権限の基本
New2
Rails
アセットの全体像をやさしく解説!importmap・jsbundling・cssbundlingの選び方
New3
Rails
Rails Action Cable入門|チャネル・接続・サブスクライブの基本を図解でやさしく解説
New4
Rails
RailsのScaffoldは使うべき?初心者向けにメリット・デメリット・安全な使い方と代替案を解説!
人気記事
No.1
Java&Spring記事人気No1
Ruby
Rubyのreduceとinject入門!合計計算や集計を初心者向けに分かりやすく解説
No.2
Java&Spring記事人気No2
Ruby
Rubyの文字列エンコーディング完全ガイド!Encoding・force_encoding・encodeを初心者向け解説
No.3
Java&Spring記事人気No3
データベース
PostgreSQLのWHERE句を徹底解説!初心者でもわかるSQLデータ抽出の基本
No.4
Java&Spring記事人気No4
Rails
Rails認可をやさしく理解!CanCanCan入門:ability.rbの定義とload_and_authorize_resource実例
No.5
Java&Spring記事人気No5
Ruby
Rubyで比較演算子を完全解説!==・===・<=>・eql? の使い分け
No.6
Java&Spring記事人気No6
Ruby
OpenSSL関連エラーの直し方を完全解説!証明書・ビルドオプション・brew対策まとめ
No.7
Java&Spring記事人気No7
データベース
MySQLとは?初心者向けにデータベースの特徴とできることをやさしく解説
No.8
Java&Spring記事人気No8
データベース
PostgreSQLのCTE(WITH句)完全解説!複雑なSQLを整理して読みやすくする書き方