Ruby Basics: Strings, Arrays, & Hashes, oh my! (and cute things)
Tags: ruby, python
Published: 2020-11-24 18:29:32

*This is a continuation of Picking up Ruby Fast, as a Python Dev. Again, expect examples with minimal math*

---

## Cute Names!!!!

{% twitter 1330968511598964737 %}

### Hashrockets `=>`

Hashrockets are used in between keys and values in a hash. It's like the `:` in a python dictionary.

```
=> # hashrocket

# ruby
pet_age = { 'cheeto' => 5, 'wiley' => '>2 ish', 'puppy' => 12, 'remmy' => 4, 'ruger' => 4 }

# python
pet_age = { 'cheeto' : 5, 'wiley' : '>2 ish', 'puppy' : 12, 'remmy' : 4, 'ruger' : 4 }
```

### Spaceship Operator `<=>`

The spaceship operator is a [tree way comparison](https://en.wikipedia.org/wiki/Three-way_comparison). It takes 2 values and compares them with each part of the spaceship then it returns 3 things. The only return values you will get from a `<=>` are `-1`, `0`, and `1`.

Spaceship operator
```python
<=> # spaceship operator

#ruby
cat_age = 12
dog_age = 5

cat_age <=> dog_age

# output
=> -1  # yep, cat is def older than dog
```

 - `-1` means `<`
 - `0` means `=`
 - `1` means `>`




---
Other than cute names, I don't have too much exciting to report today, just going through the basics to see what methods Ruby uses compared to what Python has for built-in functions. Mostly, it looks like Ruby has chosen better names. 

Oh! I did do an exciting thing. I managed to get my way through mapping some hashes together to make lists of popular movies in different categories

## Just Some Notes

A bunch of examples for future reference.

### Strings and Some Methods

#### `.prepend`
add something to the beginning of something else
```ruby
command = ", leave the cat alone!"
command.prepend("Wiley")

# output
=> "Wiley, leave the cat alone!"
```

#### `.delete`
remove specific characters from strings
```ruby
string = "Please hire me. I'm excited to learn"
string.delete "aeiou" # removing vowels

# output
=> "pls hr m. I'm xctd t lrn"
```

---
### Arrays

Ruby uses zero-based indexing, just like Python. Arrays are basically the same as Python lists. The array methods from [the Ruby docs](http://www.ruby-doc.org/core-2.2.0/Array.html) seem to basically be the same as the built-functions python has.

#### `.delete`
remove specific values from arrays
```ruby
feels = ["joyful", "irritable", "ecstatic"]
feels.delete "irritable" "mad" # removing negative words

# output
=> ["joyful", "ecstatic"]
```

though, it seems `.reject` or `.select.with_index` would be a better way to remove these. Though, I don't see what's wrong with `.delete`

```ruby
feels = ["joyful", "irritable", "ecstatic"]
feels.reject { |word| word == "irritable" || word == "mad"}

# output
=> ["joyful", "ecstatic"]
```

---
### `.map` vs `.each`
I was told the other day that whenever I see `.each` I should probably use `.map`. Today, I've learned why. `.map` collects results and `.each` does not. 

`.map` is meat to change or transform data.


```ruby
# .each returns the unchanged object
pets = ["cat", "dog", "fish"]

pets.each { |pet| pet * 2 }

# output
=> ["cat", "dog", "fish"]
```

```ruby
# .map returns the changed object
pets = ["cat", "dog", "fish"]

pets.map { |pet| pet * 2 }

# output
=> ["catcat", "dogdog", "fishfish"]
```

By the way, I've use blocks several times, but I don't think I've talked about what they do and why they are used. Blocks are the code in the curly braces after a method. In the example above, that's `{ |pet| pet * 2 }`. Blocks are used to show how we want the data to change.

---
### Hashes and Some Methods

dictionary == hash

#### `invert`
swap keys and values
```ruby
pet_age = { :cheeto => 5, :wiley => '>2 ish', :puppy => 12, :remmy => 4, :ruger => 4 }
pet_age[:chip] = 0.5 #adds to hash

pet_age.invert

# output
=> {5=>:cheeto, ">2 ish"=>:wiley, 12=>:puppy, 4=>:ruger, 0.5=>:chip}
```


#### A bigger `.map` example
```ruby
ratings = {
  :g => 'Little Ones',
  :pg => 'Family Time',
  :pg13 => 'Older Kids',
}
dictionary = {
  :g => { :one => 'ratatouille', :two => 'Wall-e', :three => 'Monsters Inc' },
  :pg => { :one => 'Tangled', :two => 'frozen', :three => 'Finding Dory' },
  :pg13 => { :one => 'Avatar', :two => 'Hamilton', :three => 'mulan' }
}

selected = ratings.select do |key, words|
  key == :g or key == :pg or key == :pg13
end

lines = selected.map do |key, section|
  movies = dictionary[key]
  parts = movies.map { |key, movie| "#{movie.split.map(&:capitalize).join(' ')}" }
  "Popular for #{section}: #{parts.join(", ")}."
end

puts lines.join("\n")


"""
# output
=> Popular for Little Ones: Ratatouille, Wall-e, Monsters Inc.
=> Popular for Family Time: Tangled, Frozen, Finding Dory.
=> Popular for Older Kids: Avatar, Hamilton, Mulan.
"""
```

In the example above, I had to use `.split.map(&:capitalize).join(' ')` to make each word in the movie name capital. This cuts the string at the space, capitalizes the parts, then puts them back together.

`.capitalize` only gets the first word and `.titleize` would work, but only if using Rails.


---
If you missed the first post in this series, I've heard it's a good read and there's cats.
{% post https://dev.to/vickilanger/python-to-ruby-1hc2 %}