Working with Arrays of Hashes

Barcelona on Rails meetup

Why?

  • Getting data from APIs
  • Building APIs to deliver data
  • Simplify SQL queries

Example of a Hash

In JSON notation

{
	"gender":"male",
	"name":{
		"title":"mr",
		"first":"kaya",
		"last":"köylüoğlu"
	},
	"location":{
		"street":"1756 fatih sultan mehmet cd",
		"city":"bayburt",
		"state":"van",
		"postcode":82603
	},
	"email":"kaya.köylüoğlu@example.com",
	"login":{
		"username":"smallduck449",
		"password":"moritz","salt":"4OThAk5p",
		"md5":"21afb8ed0d1113d7f65c05b693696c59",
		"sha1":"8eb64b2242bd6c375bd10f4ffc886e60160452e4",
		"sha256":"aa2cadb8395e8f90e53a83b98ec2273a8bc862889f10ea203fcd37847d4a8a68"
	},
	"registered":1345643832,
	"dob":1245305041,
	"phone":"(736)-954-6900",
	"cell":"(905)-844-2623",
	"id":{
		"name":"",
		"value":null
	},
	"picture":{
		"large":"https://randomuser.me/api/portraits/men/71.jpg",
		"medium":"https://randomuser.me/api/portraits/med/men/71.jpg",
		"thumbnail":"https://randomuser.me/api/portraits/thumb/men/71.jpg"
	},
	"nat":"TR"
}
						

Generated from randomuser.me API

Getting an array of Hashes

We call the URL https://randomuser.me/api?results=50


{
	"results": [ ...Array of Hashes here... ],
	"info" : ... some other info about data ...
}
						
					

From JSON string

turning a JSON string into an object and counting the elements in it

#script1.rb
require 'json'
file = File.open("apiresults.json", "rb")
contents = file.read

jsonobject = JSON.parse contents
arrayofhashes = jsonobject["results"]

puts arrayofhashes.count
								

$ ruby script1.rb
> 50
							

To JSON

Turning an actual array of Hashes into a string with JSON notation

#script2.rb
require 'json'

people = Array.new

person1 = Hash.new
person2 = Hash.new

person1["name"] = "John"
person1["surname"] = "Doe"
people.push person1

person2["name"] = "Jane"
person2["surname"] = "Smith"
people.push person2

jsonstring = people.to_json

puts jsonstring
						

$ ruby script2.rb
> [{"name":"John","surname":"Doe"},{"name":"Jane","surname":"Smith"}]
							

Select

Selecting users by gender

#script3.rb
require 'json'
file = File.open("apiresults.json", "rb")
arrayofhashes = JSON.parse(file.read)["results"]

onlymales = arrayofhashes.select{ |thehash| thehash["gender"] == 'male' }

puts "There are #{arrayofhashes.count} users"
puts "There are #{onlymales.count} males"
						

$ ruby script3.rb
> There are 50 users
> There are 27 males
						

Select!

Adding "!" applies the operation to the actual array instead of returning a different one

#script4.rb
require 'json'
file = File.open("apiresults.json", "rb")
arrayofhashes = JSON.parse(file.read)["results"]

arrayofhashes.select!{ |thehash| thehash["gender"] == 'male' }

puts "There are #{arrayofhashes.count} male users"
						

$ruby script4.rb
> There are 27 male users
						

Complex selects

Making complex operations in order to select people born on Monday

#script5.rb
require 'json'
require 'date'
file = File.open("apiresults.json", "rb")
arrayofhashes = JSON.parse(file.read)["results"]

mondayborn = arrayofhashes.select do |thehash|
	dob = DateTime.strptime(thehash["dob"].to_s,'%s')
	if dob.wday == 1
		isMonday = true
	else
		isMonday = false
	end

	isMonday
end

puts "There are #{mondayborn.count} users born in a Monday"
puts mondayborn.first["dob"].to_s + " - " + DateTime.strptime(mondayborn.first["dob"].to_s,'%s').strftime("%+")

						

$ ruby script5.rb
> There are 9 users born in a Monday
> 846489535 - Mon Oct 28 07:58:55 +00:00 1996
						

Map

Mapping the data into an Array of values

#script6.rb
require 'json'
file = File.open("apiresults.json", "rb")
arrayofhashes = JSON.parse(file.read)["results"]

firstnames = arrayofhashes.map{ |person| person["name"]["first"] }

puts firstnames
						

$ ruby script6.rb
rasmus
addison
jill
charlotte
jacob
viljami
jacob
manuel
ümit
yan
joann
benjamin
afet
volkan
misty
حسین
roman
roméo
charles
clídio
jeremiah
elbertus
cesar
luisa
kimberly
eugene
vilho
joel
katie
harold
jacinta
bruce
mathilde
léonie
daniel
ritthy
annie
vicenta
brittany
johnny
tracey
felix
olivia
rodrigo
barış
lena
adèle
laurine
jeanne
lydia
						

Sort_by

Sorting an array by a value associated to a key. Date registered

#script7.rb
require 'json'
file = File.open("apiresults.json", "rb")
arrayofhashes = JSON.parse(file.read)["results"]

arrayofhashes.sort_by!{ |thehash| thehash["registered"] }

arrayofhashes.each do |u|
	puts u["registered"]
end
						
 
$ ruby script7.rb
921143768
933542996
936159408
944306824
947733935
953326415
954336160
962050453
983606907
992142783
1003862742
1006047997
1007891146
1012104134
1019973568
1042161318
1050140720
1053206536
1055650879
1061498048
1074797328
1078143187
1097102245
1097159610
1114472735
1115864433
1126005653
1172389801
1176783890
1180045155
1196707249
1197458141
1215905254
1224923826
1253427307
1256589624
1259483610
1265237700
1288802190
1305470134
1318133973
1338934133
1342874723
1344585187
1348834633
1356240608
1391759531
1400391598
1411809695
1422089157
						

Sort

Using the spaceship operator <=>

#script8.rb
require 'json'
file = File.open("apiresults.json", "rb")
arrayofhashes = JSON.parse(file.read)["results"]

arrayofhashes.sort!{ |a,b| a["name"]["last"] <=> b["name"]["last"] }

arrayofhashes.each do |u|
	puts u["name"]["last"]
end
						

$ ruby script8.rb
adan
bates
blanchard
boorsma
bouchard
brar
brooks
brunet
chevalier
cooper
delgado
douglas
durak
duval
döring
gil
guillot
jimenez
kavaklıoğlu
kivisto
kopp
lepisto
long
lord
martinez
may
morgan
murray
neva
novaes
oliver
owens
peters
picard
pietila
poçan
schmitt
silva
smith
steward
teixeira
tuenter
turner
vranken
wainio
washington
wells
ylitalo
zimmer
محمدخان
						

Reverse sort

Getting the array in reverse order

#script9.rb
require 'json'
file = File.open("apiresults.json", "rb")
arrayofhashes = JSON.parse(file.read)["results"]

arrayofhashes.sort!{ |a,b| b["name"]["last"] <=> a["name"]["last"] }

arrayofhashes.each do |u|
	puts u["name"]["last"]
end
						

$ ruby script9.rb
محمدخان
zimmer
ylitalo
wells
washington
wainio
vranken
turner
tuenter
teixeira
steward
smith
silva
schmitt
poçan
pietila
picard
peters
owens
oliver
novaes
neva
murray
morgan
may
martinez
lord
long
lepisto
kopp
kivisto
kavaklıoğlu
jimenez
guillot
gil
döring
duval
durak
douglas
delgado
cooper
chevalier
brunet
brooks
brar
bouchard
boorsma
blanchard
bates
adan
						

Complex sort

Establishing our method to sort the data. By Birth date.

#script10.rb
require 'json'
require 'date'
file = File.open("apiresults.json", "rb")
arrayofhashes = JSON.parse(file.read)["results"]

arrayofhashes.sort! do |a,b|
	a_dob = DateTime.strptime(a["dob"].to_s,'%s')
	b_dob = DateTime.strptime(b["dob"].to_s,'%s')

	comp = a_dob.mon <=> b_dob.mon	

	if comp == 0
		comp = a_dob.day <=> b_dob.mday
	end

	comp
end

arrayofhashes.each do |u|
	puts DateTime.strptime(u["dob"].to_s,'%s').strftime("%d %b %Y")
end
						

$ruby script10.rb
19 Jan 1984
23 Jan 1986
24 Jan 1978
05 Feb 1999
06 Feb 2012
10 Feb 1997
12 Feb 1973
15 Feb 1995
28 Feb 1993
28 Feb 1983
01 Mar 1981
08 Mar 1974
10 Mar 2000
20 Mar 1981
20 Mar 1974
23 Mar 2004
28 Mar 2003
09 Apr 2007
12 Apr 1983
14 Apr 1971
17 Apr 1983
24 Apr 1995
26 Apr 2004
08 May 1993
08 May 2008
24 May 2002
05 Jun 1997
14 Jun 1997
06 Jul 2012
10 Jul 1980
11 Jul 1976
28 Jul 2014
31 Jul 2005
15 Aug 1999
16 Aug 2011
20 Aug 2003
20 Aug 2008
14 Sep 1996
21 Sep 1980
04 Oct 2000
08 Oct 2010
10 Oct 1981
19 Oct 1989
26 Oct 1995
28 Oct 1996
30 Oct 2009
02 Nov 1993
19 Nov 1996
23 Nov 2004
28 Dec 1989
						

Each

Getting the data and adding our stuff to it. Timestamp added to DB

#script11.rb
require 'json'
require 'date'
file = File.open("apiresults.json", "rb")
arrayofhashes = JSON.parse(file.read)["results"]

arrayofhashes.each { |thehash|  thehash["addedToDB"] = Time.now }

puts arrayofhashes.first
						

{
"gender"=>"male",
"name"=>{ 
	"title"=>"mr", 
	"first"=>"rasmus", 
	"last"=>"kivisto"
	},
"location"=>{
	"street"=>"5731 fredrikinkatu",
	"city"=>"sastamala",
	"state"=>"åland",
	"postcode"=>56788
}, 
"email"=>"rasmus.kivisto@example.com",
"login"=>{
	"username"=>"redgoose892",
	"password"=>"reason",
	"salt"=>"dQkNDMrn",
	"md5"=>"93f2e2c86204f6803ffc05d4d8530be0",
	"sha1"=>"b5b8cdef968c3e4722604e2a2c26d07b10f1e6b1",
	"sha256"=>"31618d83c8c9abb5cee3248d37ac2abaf586b13a5170836fead81703c509d555"
	},
"registered"=>1197458141,
"dob"=>1219227520,
"phone"=>"07-599-929",
"cell"=>"044-226-29-76",
"id"=>{
	"name"=>"HETU", "value"=>"48162027-O"
	},
"picture"=>{
	"large"=>"https://randomuser.me/api/portraits/men/36.jpg",
	"medium"=>"https://randomuser.me/api/portraits/med/men/36.jpg",
	"thumbnail"=>"https://randomuser.me/api/portraits/thumb/men/36.jpg"
	},
"nat"=>"FI",
"addedToDB"=>2016-07-20 22:49:25 +0200
}
						

More info...

http://ruby-doc.org/core-2.3.1/Array.html
http://ruby-doc.org/core-2.3.1/Hash.html

THE END