Hello! Recently I began to study ruby, I decide homework:
In the csv file, the temperature indicators for each day are displayed in the form of:

30.01, -7 31.01, -10 01.02, 0 

...etc

Parse the file, calculate and display the average temperature for each month. Code verification via rubocop

 CSV.read('/home/natasha/Документы/CSV/temperature.csv') #вывожу даные из csv файла в irb консоль #наверное это не очень правильно, но не знаю, как обратиться к массиву array = [["1.01", "0"], ["2.01", "4"], ["3.01", "1"], ["4.01", "0"], ["5.01", "3"], ["6.01", "-12"], ["7.01", "-14"], ["8.01", "-8"], ["9.01", "-3"], ["10.01", "-1"], ["11.01", "-5"], ["12.01", "-5"], ["13.01", "4"], ["14.01", "2"], ["15.01", "-3"], ["16.01", "-7"], ["17.01", "-6"], ["18.01", "-7"], ["19.01", "-2"], ["20.01", "0"], ["21.01", "0"], ["22.01", "0"], ["23.01", "-2"], ["24.01", "-3"], ["25.01", "-9"], ["26.01", "-4"], ["27.01", "-4"], ["28.01", "-3"], ["29.01", "-9"], ["30.01", "-8"], ["31.01", "-8"], ["1.02", "-6"], ["2.02", "-3"], ["3.02", "-1"], ["4.02", "1"], ["5.02", "-2"], ["6.02", "-5"], ["7.02", "-10"], ["8.02", "-12"], ["9.02", "-7"], ["10.02", "-6"], ["11.02", "-5"], ["12.02", "-5"], ["13.02", "-3"], ["14.02", "0"], ["15.02", "1"], ["16.02", "1"], ["17.02", "1"], ["18.02", "4"], ["19.02", "2"], ["20.01", "1"], ["21.02", "4"], ["2.02", "6"], ["23.02", "5"], ["24.02", "12"], ["25.02", "2"]] array1 = array.flatten #"сплющиваю массив" #=>["1.01", "0", "2.01", "4", "3.01", "1", "4.01", "0", "5.01", "3", "6.01", "-12", "7.01", "-14", "8.01", "-8", "9.01", "-3", "10.01", "-1", "11.01", "-5", "12.01", "-5", "13.01", "4", "14.01", "2", "15.01", "-3", "16.01", "-7", "17.01", "-6", "18.01", "-7", "19.01", "-2", "20.01", "0", "21.01", "0", "22.01", "0", "23.01", "-2", "24.01", "-3", "25.01", "-9", "26.01", "-4", "27.01", "-4", "28.01", "-3", "29.01", "-9", "30.01", "-8", "31.01", "-8", "1.02", "-6", "2.02", "-3", "3.02", "-1", "4.02", "1", "5.02", "-2", "6.02", "-5", "7.02", "-10", "8.02", "-12", "9.02", "-7", "10.02", "-6", "11.02", "-5", "12.02", "-5", "13.02", "-3", "14.02", "0", "15.02", "1", "16.02", "1", "17.02", "1", "18.02", "4", "19.02", "2", "20.01", "1", "21.02", "4", "2.02", "6", "23.02", "5", "24.02", "12", "25.02", "2"] 

Do not judge strictly. Help, please tell me the right way. I just do not know how to do next. I thought I could get whole numbers from an array, and then calculate the arithmetic average of them. In general, to be honest, I'm confused, I have been sitting for the second day and can’t think of anything.

  • And for what purpose did you flatten an array? - D-side

1 answer 1

Break the task into several small subtasks:

  1. Extract the last elements of the internal arrays ["25.02", "2"] => "2"
  2. Convert a string to the number "2" => 2
  3. Get the array of the last elements of the array
  4. Calculate the sum of the elements of the array
  5. Get arithmetic average

This is called decomposition, it is very difficult to explain and teach this, teachers want you to come to this. It does not work right away - nothing terrible, in time it will come, do not lower the main hand, but try to split the complex task into parts.

Now solve each of these tasks consistently. You already have an array of arrays

 array = [["1.01", "0"], ["2.01", "4"], ..., ["25.02", "2"]] 

You need to get an array of the last elements of the internal arrays. Do not solve the problem right in the forehead. Take a separate item, for example, ["25.02", "2"] and work with it. In Ruby, everything is an object; to use its methods, you need to know a class. Sure, not sure about the class name, at first always check the class name

 ["25.02", "2"].class # Array 

Even if you know some methods of the Array class, you still go to the http://ruby-doc.org documentation. Enter the name Array in the class field, go to the Array page and familiarize yourself with its methods, until there is something left there that you wouldn’t remember without consulting the documentation. Look for methods to solve your problem. In particular, you will find there the first and last methods, which retrieve the first and last elements of the array. for example

 ["25.02", "2"].last # "2" 

We try to add two lines - we get a strange result - this is clearly not the case.

 "2" + "5" # 25 

Strings are concatenated, instead of adding numbers, we need to explicitly cast the strings to whole numbers. Just in case, look at the class that actually turns out to be a string.

 "2".class # String 

We go to the documentation of the class String and read everything from beginning to end. We do this until everything is familiar there. Find the method to convert to the number to_i . We try

 "2".to_i + "5".to_i # 7 

It turned out what was required. Now we get an array consisting of the last elements of the array, converted to an integer. To solve the problem, you need to at least cycle through the resulting array. In Ruby, cycles are not used; almost all problems are solved using iterators. I can assume that it is the use of iterators that makes you difficult. Unfortunately or fortunately, programming in Ruby without an understanding of iterators will fail, they will have to be mastered at the level of complete understanding (like variables, cycles and conditional operators in other languages).

In order to get an array of the last elements, we can use the collect iterator, which passes through all the elements of the collection and provides a block, the result of which becomes the corresponding element of the new collection

 array = [["1.01", "0"], ["2.01", "4"], ["25.02", "2"]] array.collect { |x| x.last } # ["0", "4", "2"] 

Due to the to_proc method, the above construction can be reduced to

 array = [["1.01", "0"], ["2.01", "4"], ["25.02", "2"]] array.collect(&:last) # ["0", "4", "2"] 

This is not syntactic sugar, it is a block transfer method, in which the to_proc method is implicitly applied to the symbol :last ( to_proc tricks should be understood as well as iterators)

 array = [["1.01", "0"], ["2.01", "4"], ["25.02", "2"]] array.collect { |x| :last.to_proc.call(x) } # ["0", "4", "2"] 

When choosing a solution, remember that, as in the linguistic language, programming preference is given to the shortest structure.

Now that we have an array of strings, we need to convert them to an integer.

 array = [["1.01", "0"], ["2.01", "4"], ["25.02", "2"]] array.collect(&:last).collect(&:to_i) # [0, 4, 2] 

Now the task is to summarize the elements of the array and get one number. You can use the ready sum method

 array = [["1.01", "0"], ["2.01", "4"], ["25.02", "2"]] array.collect(&:last).collect(&:to_i).sum # 6 

However, for educational purposes, it makes sense to master the iterator inject or each_with_object (they are important to understand, you will often meet them in someone else's code, so you need to understand well why they behave this way)

 array = [["1.01", "0"], ["2.01", "4"], ["25.02", "2"]] array.collect(&:last).collect(&:to_i).inject(0){ |x, m| x + m } # 6 array.collect(&:last).collect(&:to_i).inject(&:+) # 6 

Now assemble these bricks into a single program, getting the sum of the elements and then the average, driving the code of the working program through Rubocop (preferably stopping at all the comments and working through them).

In fact, these tasks are to repeatedly read the documentation and master the techniques of working with iterators and blocks. It is very important to solve them, constantly referring to the documentation, repeatedly reading it again and again. There is almost no talk about this in books, they rarely talk about it, but believe me, this is exactly what they do when they become a programming star — you will get information from the source code, but while you have difficulty solving educational tasks, go to the documentation for any plug-in and read it from beginning to end. Especially in the case of Ruby, the documentation is excellent.