Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Ruby Dictionary

  1. Home
  2. Ruby Dictionary
  3. Hash.filter_map / flat_map / reduce

Hash.filter_map / flat_map / reduce

Since: Ruby 2.7(2019)

Covers filter_map for simultaneous filtering and transformation on hashes, flat_map for flattening nested results, and the aggregation methods reduce and inject.

Syntax

hash.filter_map { |key, value| transformed_value or nil/false }

# Returns an array with block results flattened one level.
hash.flat_map { |key, value| array }

# Aggregates all pairs into a single value.
hash.reduce(initial) { |accumulator, (key, value)| ... }
hash.inject(initial) { |accumulator, (key, value)| ... }

# Returns a hash with pairs grouped by the block's return value.
hash.group_by { |key, value| group_key }

Method List

MethodDescription
filter_map { |k, v| ... }Includes an element in the result array only when the block returns a value other than nil or false.
flat_map { |k, v| ... }Concatenates the arrays returned by the block into a single array. When the block does not return an array, it behaves the same as map.
reduce(init) { |acc, (k, v)| ... }Starts from an initial value, accumulates each pair, and returns the final result. inject is an alias.
min_by { |k, v| ... }Returns the pair with the smallest block return value as [key, value].
max_by { |k, v| ... }Returns the pair with the largest block return value.
sort_by { |k, v| ... }Returns an array sorted by the block's return value.
group_by { |k, v| ... }Returns a hash with pairs grouped by the block's return value.

Sample Code

sample_hash_filter_map_flat_map.rb
enforcers = { kogami: 5, ginoza: 0, masaoka: 8, karanomori: 0, tsunemori: 3 }

# filter_map: get only active member names (select + map in one pass)
active = enforcers.filter_map { |member, score| member.to_s if score > 0 }
puts active.inspect # ["kogami", "masaoka", "tsunemori"]

# flat_map: expand each pair into multiple strings
labels = enforcers.flat_map { |member, score| [member.to_s, score.to_s] }
puts labels.inspect
# ["kogami", "5", "ginoza", "0", "masaoka", "8", "karanomori", "0", "tsunemori", "3"]

# reduce: calculate the total score
total = enforcers.reduce(0) { |sum, (_, score)| sum + score }
puts "Total score: #{total}" # Total score: 16

# reduce: build a hash of active members only
active_hash = enforcers.reduce({}) do |hash, (member, score)|
  hash[member] = score if score > 0
  hash
end
puts active_hash.inspect # {:kogami=>5, :masaoka=>8, :tsunemori=>3}

# min_by / max_by: find the member with the least and most score
puts enforcers.min_by { |_, score| score }.inspect # [:ginoza, 0]
puts enforcers.max_by { |_, score| score }.inspect # [:masaoka, 8]

# sort_by: sort by score
sorted = enforcers.sort_by { |_, score| score }
sorted.each { |member, score| puts "#{member}: #{score}" }

Running the code produces the following output:

ruby hash_filter_map_flat_map.rb
["kogami", "masaoka", "tsunemori"]
["kogami", "5", "ginoza", "0", "masaoka", "8", "karanomori", "0", "tsunemori", "3"]
Total score: 16
{:kogami=>5, :masaoka=>8, :tsunemori=>3}
[:ginoza, 0]
[:masaoka, 8]
ginoza: 0
karanomori: 0
tsunemori: 3
kogami: 5
masaoka: 8

Notes

filter_map was added in Ruby 2.7. It performs filtering and transformation in a single iteration. It combines the two-step select { }.map { } pattern into one, improving performance and reducing code length.

reduce (also inject) is powerful but can hurt readability. When you only need a sum, minimum, or maximum, prefer the more expressive sum, min_by, or max_by. For building a hash, each_with_object is often easier to read.

Using sort_by on a hash returns an array of pairs. To convert the result back to a hash, append to_h at the end. For multi-criteria sorting, return an array from the block (e.g., sort_by { |k, v| [v, k.to_s] }).

If you find any errors or copyright issues, please .