Featured image of post Ruby Mini Project: Reading and Filtering csv data

Ruby Mini Project: Reading and Filtering csv data

Learn how to read csv data and filter it

Intro

This is a fun project to extract pokemon data from csv using Ruby.

What we learn

In this project we’ll learn

  • How to load and work with CSV in Ruby
  • How to filter array data

Requirement

Problem

As we see in the image below,

Pokemon List

I want to choose grass-type pokemon with has attack in medium level, no more than 100 and no less than 90 attack attribute.

Solution

To solve the problem, let’s create some experiment using irb console.

Filter a row

  1. Import CSV standard library by run require "csv".
  2. Load CSV data and store in a variable, pokemons = CSV.read("pokemon.csv")
  3. Read data on row 1 by using, pokemens[1]
  4. There are two columns that mark the type of Pokemon, 2 and 3. So we should check these columns. pokemons[1][2] == "Grass" || pokemons[1][3] == "Grass"
  5. Then we check column 6 from the table to get attack data, convert to integer, and check the range value. pokemons[1][6].to_i.between?(90,100)
  6. Put together in a method
1
2
3
4
5
6
7
require "csv"

pokemons = CSV.read("pokemon.csv")

def is_pokemon_type?(pokemon)
  (pokemon[2] == "Grass" || pokemon[3] == "Grass") && pokemon[6].to_i.between?(90, 100)
end

Filter all rows

Then, to get all rows that meet the criteria we create loop

1
2
3
4
5
6
7
selected_pokemons = []

for i in 0...pokemons.size do
    if is_pokemon_type?(pokemons[i])
        selected_pokemons << pokemons[i]
    end
end

The result can be seen by running p selected_pokemons

Use blocks

From the function we defined earlier

1
2
3
def is_pokemon_type?(pokemon)
  return (pokemon[2] == "Grass" || pokemon[3] == "Grass") && pokemon[6].to_i.between?(90, 100)
end

and turn it into a block

1
{ |pokemon| (pokemon[2] == "Grass" || pokemon[3] == "Grass") && pokemon[6].to_i.between?(90, 100) }

It’s a different syntax, but it looks a lot like a function. There are some operations on arrays that can take it and do stuff with it (https://ruby-doc.org/core-3.1.0/Array.html). In our case, we use select method

1
pokemons.select{ |pokemon| (pokemon[2] == "Grass" || pokemon[3] == "Grass") && pokemon[6].to_i.between?(90, 100) }

Additional Featurs

The final code will be

1
2
3
4
5
6
require "csv"

CSV.read("pokemon.csv")
  .select {|pokemon| (pokemon[2] == "Grass" || pokemon[3] == "Grass") && pokemon[6].to_i.between?(90, 100) }
  .sort_by {|pokemon| pokemon[6].to_i}
  .each {|pokemon| puts pokemon.join(',')}

with additional feature i.e. sort_by.

Full list of method can be shown here https://ruby-doc.org/core-3.1.0/Array.html

Additional Resources

There are lot of resources about block in Ruby:

  1. https://www.oreilly.com/content/using-blocks-in-ruby/
  2. https://medium.com/@noordean/understanding-ruby-blocks-3a45d16891f1
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy