rubyguides

Hash#keys

hash.keys

Hash#keys returns a new array containing all the keys from the hash, in insertion order. This method is useful when you need to iterate over all keys or when you need a list of keys for set operations.

Syntax

hash.keys

Examples

Calling keys on any hash returns a new array. The array contains every key in insertion order, which is the order the keys were added to the hash since Ruby 1.9. This guarantee makes the output predictable even when the hash is built incrementally.

Basic key extraction

user = { name: "Alice", email: "alice@example.com", age: 30 }

user.keys
# => [:name, :email, :age]

Iteration with keys

Once you have the key array, you can iterate over it with any Enumerable method. This is a common pattern when you need to process each entry in a collection and the order of keys matters. The iteration block receives each key, and you look up the corresponding value from the original collection:

config = { host: "localhost", port: 3000, ssl: true }

config.keys.each do |key|
  puts "#{key}: #{config[key]}"
end

# Output:
# host: localhost
# port: 3000
# ssl: true

Converting to a set

Because keys returns a plain array, you can use Ruby’s array intersection (&), union (|), and difference (-) operators directly on the result. These set operations are a concise way to compare what two hashes share or differ on at the key level:

h1 = { a: 1, b: 2 }
h2 = { b: 3, c: 4 }

# Find common keys
(h1.keys & h2.keys)
# => [:b]

Common Patterns

The following patterns show how keys combines with other Ruby methods to solve everyday tasks. Each one is a one-liner or short block, but they are worth knowing because they appear frequently in real code and the approach scales well to larger hashes:

Check if a key exists

data = { name: "Bob", active: true }

data.keys.include?(:name)
# => true

data.keys.include?(:missing)
# => false

However, using Hash#has_key? or Hash#include? is more efficient for this purpose. The keys array approach allocates a new array just to check membership, which is unnecessary when the hash already has a direct method for the same question. Use keys.include? only when you already need the key array for something else.

Transform keys

hash = { first_name: "John", last_name: "Doe" }

hash.keys.map(&:to_s)
# => ["first_name", "last_name"]

Sorting keys

Sorting the key array gives you a deterministic order regardless of insertion order. This is useful for display purposes, generating consistent output, or preparing keys for comparison with another sorted list. The sort call returns a new array and does not modify the original hash or the key list:

scores = { bob: 95, alice: 87, charlie: 92 }

scores.keys.sort
# => [:alice, :bob, :charlie]

Get all values as well

When you need both the key list and the value list, keys pairs naturally with each_value or values. The two calls are independent, so you can fetch the keys and values in separate steps without coupling them into a single data structure:

h = { x: 10, y: 20 }

h.keys
# => [:x, :y]

h.each_value.to_a
# => [10, 20]

Edge Cases

keys handles edge cases consistently. The return value is always a new array, never the hash’s internal storage, so modifying the returned array does not affect the original hash. This isolation is important when you pass the key list to code that might mutate it:

Empty hash

{}.keys
# => []

Integer keys

Ruby hashes accept integer keys just like symbol or string keys. The keys method returns them as integers, preserving their type in the output array. There is no automatic conversion to symbols or strings, so the type you use for insertion is the type you get back:

{ 1 => "one", 2 => "two" }.keys
# => [1, 2]

Mixed key types

A single hash can hold keys of different types simultaneously. keys returns them all in insertion order, with each key keeping its original type in the array. This flexibility is part of Ruby’s design, though in practice most hashes use a single key type for clarity:

{ "name" => "Alice", :age => 25, 3 => "three" }.keys
# => ["name", :age, 3]

using keys for inspection and iteration

keys is useful when you need a simple list of the names in a hash, whether that is for display, filtering, or a small comparison. It keeps the code clear because the data structure itself stays unchanged while the keys are handed off to the next step. That makes it a practical choice for iteration and quick checks, especially when the data structure is already established and only the key set needs to be inspected.

The method is also a good bridge between a map-like structure and array-style processing. Once the keys are in an array, they can be sorted, sliced, or compared with another key list using familiar array tools. That makes keys a convenient first step when the collection needs to be viewed from a different angle without changing the original data.

It is a small method, but it can make a program easier to inspect when the hash is part of a larger configuration or result object. The key list gives the caller a compact summary of what is present without exposing the values yet. That can be enough for a menu, a report, or a quick check before a later step uses the hash more directly.

See Also