Ruby Data Structures: Difference between revisions

From Wiki
Jump to navigation Jump to search
 
(21 intermediate revisions by the same user not shown)
Line 5: Line 5:
2e-20                  # Float
2e-20                  # Float
?a                    # character code for 'a', which is 97
?a                    # character code for 'a', which is 97
1_048_576              # same as 1048576
Float::MIN            # 2.2250738585072e-308 (on this machine)
Float::MAX            # 1.79769313486232e+308
Float::EPSILON        # 2.22044604925031e-16
</source>
=== Operations ===
<source lang="ruby">
8.to_f              # 8.0
64**2              # 4096
b = 64**0.5        # 8.0
</source>
=== Random Numbers ===
<source lang="ruby">
a = rand      # Float in [0, 1)
a = rand(10)  # Fixnum in 0 <= a < 10
</source>
=== Math ===
<source lang="ruby">
Math.sqrt(4)    # 2.0
</source>
=== Parsing Strings to get Numbers ===
<source lang="ruby">
"123".to_i          # 123
Integer("123")      # 123
"junk".to_i        # silently returns 0
Integer("junk")    # error
"123junk".to_i      # 123
Integer("123junk")  # error
" 123 ".to_i        # 123
Integer(" 123 ")    # 123
"3.1416".to_f      # 3.1416
Float("2.718")      # 2.718
"2.9979246e5".to_f  # 299792.46
Float("6.02e23")    # 6.02e23
</source>
=== Formatting Numbers ===
<source lang="ruby">
x = 345.6789
printf("x = %6.2f\n", x)  # x = 345.68, prints immediately
sprintf("x = %6.2f\n", x)  # returns a String
"x = %6.2f\n" % x          # same thing
</source>
</source>


Line 26: Line 72:
letter
letter
</source>
</source>
NOTE: if you want to indent the closing "letter", use <code><<-letter</code> to start the here document


=== Concatenation ===
=== Concatenation ===
Line 71: Line 118:
x.include? "bc"  # true
x.include? "bc"  # true
x["cde"] = "CDE"  # x is now "abCDEfg"
x["cde"] = "CDE"  # x is now "abCDEfg"
x.count("ae")    # 2, the number of matching characters
</source>
</source>


Line 91: Line 139:
x.empty?          # false
x.empty?          # false
x.upcase          # "ABCDEFG"
x.upcase          # "ABCDEFG"
x.upcase.downcase # "abcdefg"
x.reverse        # "gfedcba"
x.delete("ae")    # "bcdfg"
"abc\r\n".chomp  # "abc", remove trailing newline chars
"abc\r\n".chomp  # "abc", remove trailing newline chars
" \tabc\n".strip  # "abc", trim whitespace  
" \tabc\n".strip  # "abc", trim whitespace  
ruler = "+" + ("."*4+"5"+"."*4+"+")*3  # "+....5....+....5....+....5....+"
ruler = "+" + ("."*4+"5"+"."*4+"+")*3  # "+....5....+....5....+....5....+"
</source>
=== MD5 hash ===
<source lang="ruby">
require 'md5'  # already included in Rails
secret = Digest::MD5.hexdigest(password)
</source>
=== Encoding and Decoding base64 Strings ===
<source lang="ruby">
x = "abcdefg"
[x].pack("m")              # "YWJjZGVmZw==\n"
[x].pack("m").unpack("m")  # ["abcdefg"]
</source>
</source>


Line 106: Line 170:
<source lang="ruby">
<source lang="ruby">
[1, 2, 3] << 4        # [1, 2, 3, 4]
[1, 2, 3] << 4        # [1, 2, 3, 4]
[1, 2] |= [3, 4]      # [1, 2, 3, 4]
</source>
</source>


Line 117: Line 182:
<source lang="ruby">
<source lang="ruby">
my_array.each do |e| { do something with e }
my_array.each do |e| { do something with e }
</source>
or
<source lang="ruby">
for e in my_array
  do something with e
end
</source>
</source>


Line 129: Line 200:
x[0,2]              # ["a", "b"]
x[0,2]              # ["a", "b"]
x[0..2]            # ["a", "b", "c"]
x[0..2]            # ["a", "b", "c"]
x[1..-1]            # ["b", "c"]
x.index("a")        # 0
x.index("a")        # 0
x.include? "a"      # true
x.include? "a"      # true
Line 214: Line 286:
<source lang="ruby">
<source lang="ruby">
my_time = Time.local(2007, 9, 11, 17, 30, 13)  # Tue Sep 11 17:30:13 -0700 2007
my_time = Time.local(2007, 9, 11, 17, 30, 13)  # Tue Sep 11 17:30:13 -0700 2007
another_date = '2011-09-21'.to_date
yet_another = DateTime.strptime('2015-04-27 4:45 PM', '%Y-%m-%d %H:%M %p')
</source>
</source>


Line 226: Line 300:
<source lang="ruby">
<source lang="ruby">
require 'date'
require 'date'
xmas = Date.parse('12/25/2010')  # works for usual formats
today = Date.today
today = Date.today
today.to_s                        # "2007-09-12"
today.to_s                        # "2007-09-12"

Latest revision as of 23:57, 27 April 2015

Numbers

123                    # integer of type Fixnum
12345678901234567890   # Bignum:  an integer of arbitrary length
2e-20                  # Float
?a                     # character code for 'a', which is 97
1_048_576              # same as 1048576
Float::MIN             # 2.2250738585072e-308 (on this machine)
Float::MAX             # 1.79769313486232e+308
Float::EPSILON         # 2.22044604925031e-16

Operations

8.to_f              # 8.0
64**2               # 4096
b = 64**0.5         # 8.0

Random Numbers

a = rand      # Float in [0, 1)
a = rand(10)  # Fixnum in 0 <= a < 10

Math

Math.sqrt(4)    # 2.0

Parsing Strings to get Numbers

"123".to_i          # 123
Integer("123")      # 123
"junk".to_i         # silently returns 0
Integer("junk")     # error
"123junk".to_i      # 123
Integer("123junk")  # error
" 123 ".to_i        # 123
Integer(" 123 ")    # 123
"3.1416".to_f       # 3.1416
Float("2.718")      # 2.718
"2.9979246e5".to_f  # 299792.46
Float("6.02e23")    # 6.02e23

Formatting Numbers

x = 345.6789
printf("x = %6.2f\n", x)   # x = 345.68, prints immediately
sprintf("x = %6.2f\n", x)  # returns a String
"x = %6.2f\n" % x          # same thing

Strings

Literals

  • "abc": Double-quoted strings allow substitution and backslash notation.
  • 'abc': Single-quoted strings don't allow substitution and allow backslash notation only for \\ and \'.
  • alternate string literals with %q (equivalent to single quote) and %Q (equivalent to double quote):
s1 = %q[As Magritte said, "Ceci n'est pas une pipe."]
s2 = %q*\r is a control-M and \n is a control-J.*
  • Here document: create a multi-line string, allowing substitution:
name = "Bill"
letter = <<letter
Dear #{name},
I got your letter!
Sincerely,
Scott
letter

NOTE: if you want to indent the closing "letter", use <<-letter to start the here document

Concatenation

"foo" "bar"           # means "foobar"
"foo" + "bar"         # means "foobar"
"foo" << "bar"        # means "foobar"

Substitution

"The value is #{ some expression }."     # substitute the value of an arbitrary expression
"My name is #{$name}."                   # substitute the value of a variable
"My name is #$name."                     # shortcut; only works for global, class, instance variables
str = proc {|x,y,z| "The numbers are #{x}, #{y}, and #{z}" }
s1 = str.call(3,4,5)   # The numbers are 3, 4, and 5

# formatted output
name = "Bob"
age = 28
str = sprintf("Hi, %s... I see you're %d years old.", name, age)
str = sprintf("%-20s  %3d", name, age)
str = "%-20s  %3d" % [name, age]  # Same as previous example

# sub and gsub
"abababa".sub("a", "A")   # "Abababa"
"abababa".gsub("a", "A")  # "AbAbAbA"
"bacon, spam, and eggs".sub(/(\w+), (\w+),/,'\2, \1,')    # "spam, bacon, and eggs"
"Don't forget the spam.".sub(/spam/) { |m| m.reverse }     # "Don't forget the maps."

Substring

x = "abcdefg"
x[2..4]           # "cde"  (chars 2 through 4 inclusive)
x[2...4]          # "cd"   (chars 2 and 3)
x[-3..-2]         # "ef"
x[2,4]            # "cdef" (extract a string of length 4)
x[-3,2]           # "ef"
x[2]              # 99     (ascii code for "c")
x[2].chr          # "c"
x["bc"]           # "bc"
x["cb"]           # nil
x[/bc/]           # "bc"
x.include? "bc"   # true
x["cde"] = "CDE"  # x is now "abCDEfg"
x.count("ae")     # 2, the number of matching characters

Regular Expression

"I am a leaf on the wind...".scan(/\w+/)      # ["I", "am", "a", "leaf", "on", "the", "wind"]

Split

"a b c".split          # ["a", "b", "c"]
"a, b, c".split(/, /)  # ["a", "b", "c"]

Methods

x = "abcdefg"
x.size            # 7
x.length          # 7
x.empty?          # false
x.upcase          # "ABCDEFG"
x.upcase.downcase # "abcdefg"
x.reverse         # "gfedcba"
x.delete("ae")    # "bcdfg"
"abc\r\n".chomp   # "abc", remove trailing newline chars
" \tabc\n".strip  # "abc", trim whitespace 
ruler = "+" + ("."*4+"5"+"."*4+"+")*3   # "+....5....+....5....+....5....+"

MD5 hash

require 'md5'   # already included in Rails
secret = Digest::MD5.hexdigest(password)

Encoding and Decoding base64 Strings

x = "abcdefg"
[x].pack("m")               # "YWJjZGVmZw==\n"
[x].pack("m").unpack("m")   # ["abcdefg"]

Arrays

Create

x = [1, 2, 3]
x = %w(foo bar baz)        # ["foo", "bar", "baz"]

Concatenate

[1, 2, 3] << 4         # [1, 2, 3, 4]
[1, 2] |= [3, 4]       # [1, 2, 3, 4]

Iterate

my_array.each do | element |
  do something with element
end

or

my_array.each do |e| { do something with e }

or

for e in my_array
  do something with e
end

Methods

x = ["a", "b", "c"]
x.length            # 3
x.first             # "a"
x.last              # "c"
x.last(2)           # ["b", "c"]
x[0]                # "a"
x[0,2]              # ["a", "b"]
x[0..2]             # ["a", "b", "c"]
x[1..-1]            # ["b", "c"]
x.index("a")        # 0
x.include? "a"      # true
x << "d"            # ["a", "b", "c", "d"]
[1, 2, 1].uniq      # [1, 2]
x.pop               # "c", x is ["a", "b"]
x.push("d")         # ["a", "b", "c", "d"]
x.delete("b")       # returns "b", leaves x == ["a", "c"]
x.join              # "abc"
x.join(", ")        # "a, b, c"
x.map{|e| e.upcase} # ["A", "B", "C"]
x.reverse           # ["c", "b", "a"]
x.reverse.sort      # ["a", "b", "c"]
x.sort_by! {|a| a.name}  # sort on name attribute

Set operations

x = ["a", "b", "c"]
y = ["b", "c", "d"]
x & y               # ["b", "c"]
x - y               # ["a"]
x | y               # ["a", "b", "c", "d"]

Range operators

5..10 includes the number 10, but 5...10 does not.

Do not confuse ranges with arrays. These two assignments are entirely different:

x = 1..5
x = [1, 2, 3, 4, 5]

However, there is a convenient method to_a for converting ranges to arrays.

Array expansion

Also called the "splat" operator

x = [1, 2, 3]
a, b, c = *x  # now a is 1, b is 2, c is 3

Hashes

Iterate

x = {:a => 1, :b => 2, :c => 3}
x.each{|k,v| print "(#{k}, #{v})"}    # (b, 2)(c, 3)(a, 1)
x.each do |k,v|
...do something with k, v
end
x.each_key{|k| print k}               # bca
x.each_value{|v| print v}             # 231

Methods

x = {:a => 1, :b => 2, :c => 3}
x.key? :b                 # true
x.keys                    # [:b, :c, :a]
x.value? 2                # true
x.values                  # [2, 3, 1]
x[:a]                     # 1
x.delete :c               # x is {:b=>2, :a=>1}
x = {:b=>2, :a=>1}
y = {:b => 22, :c => 33}
x.merge y                 # {:b=>22, :c=>33, :a=>1}
x.clear                   # {}
x.empty?                  # true

Date and Time

What time is it now?

now = Time.now    # Wed Sep 12 11:51:41 -0700 2007
now.year          # 2007
now.month         # 9
now.day           # 12
now.wday          # 3
now.hour          # 11
now.min           # 51
now.sec           # 41

Create an arbitrary date:

my_time = Time.local(2007, 9, 11, 17, 30, 13)  # Tue Sep 11 17:30:13 -0700 2007
another_date = '2011-09-21'.to_date
yet_another = DateTime.strptime('2015-04-27 4:45 PM', '%Y-%m-%d %H:%M %p')

Date-time arithmetic:

diff = now - my_time    # 66088.978569  (in seconds)
diff/(60*60)            # 18.3580496025 (in hours)
now + 24*60*60          # Thu Sep 13 11:51:41 -0700 2007

Date-only:

require 'date'
xmas = Date.parse('12/25/2010')   # works for usual formats
today = Date.today
today.to_s                        # "2007-09-12"
yesterday = Date.new(2007, 9, 11)
yesterday.to_s                    # "2007-09-11"
today - yesterday                 # Rational(1, 1)
tomorrow = today + 1
tomorrow.to_s                     # "2007-09-13"