Extracting Portions of Hashes

Problem

You have a hash that contains a lot of values, but only a few of them are interesting. You want to select the interesting values and ignore the rest.

Solution

You can use the Hash#select method to extract part of a hash that follows a certain rule. Suppose you had a hash where the keys were Time objects representing a certain date, and the values were the number of web site clicks for that given day. We'll simulate such as hash with random data:

	require 'time'
	click_counts = {}
	1.upto(30) { |i| click_counts[Time.parse("2006-09-#{i}")] = 400 + rand(700) }
	p click_counts
	# {Sat Sep 23 00:00:00 EDT 2006=>803, Tue Sep 12 00:00:00 EDT 2006=>829,
	# Fri Sep 01 00:00:00 EDT 2006=>995, Mon Sep 25 00:00:00 EDT 2006=>587,
	# …

You might want to know the days when your click counts were low, to see if you could spot a trend. Hash#select can do that for you:

	low_click_days = click_counts.select {|key, value| value < 450 }
	# [[Thu Sep 14 00:00:00 EDT 2006, 449], [Mon Sep 11 00:00:00 EDT 2006, 406],
	# [Sat Sep 02 00:00:00 EDT 2006, 440], [Mon Sep 04 00:00:00 EDT 2006, 431],
	# …

 

Discussion

The array returned by Hash#select contains a number of key-value pairs as two-element arrays. The first element of one of these inner arrays is a key into the hash, and the second element is the corresponding value. This is similar to how Hash#each yields a succession of two-element arrays.

If you want another hash instead of an array of key-value pairs, you can use Hash#inject instead of Hash#select. In the code below, kv is a two-element array containing a key-value pair. kv[0] is a key from click_counts, and kv[1] is the corresponding value.

	low_click_days_hash = click_counts.inject({}) do |h, kv|
	 k, v = kv
	 h[k] = v if v < 450
	 h
	end
	# => {Mon Sep 25 00:00:00 EDT 2006=>403,
	# Wed Sep 06 00:00:00 EDT 2006=>443,
	# Thu Sep 28 00:00:00 EDT 2006=>419}

You can also use the Hash.[] constructor to create a hash from the array result of Hash#select:

	low_click_days_hash = Hash[*low_click_days.flatten]
	# => {Thu Sep 14 00:00:00 EDT 2006=>449, Mon Sep 11 00:00:00 EDT 2006=>406,
	# Sat Sep 02 00:00:00 EDT 2006=>440, Mon Sep 04 00:00:00 EDT 2006=>431,
	# …

 

See Also

  • Recipe 4.13, " Extracting Portions of Arrays"


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net