Best approach for deleting when using Array.combination()? - ruby

I want to compare every object in lectures with each other and if some_condition is true, the second object has to be deleted:
toDelete=[]
lectures.combination(2).each do |first, second|
if (some_condition)
toDelete << second
end
end
toDelete.uniq!
lectures=lectures-toDelete
I got some weird errors while trying to delete inside the .each loop, so I came up with this approach.
Is there a more efficient way to do this?
EDIT after first comments:
I wanted to keep the source code free of unnecessary things, but now that you ask:
The elements of the lectures array are hashes containing data of different university lectures, like the name, room,the calendar weeks in which they are taught and begin and end time.
I parse the timetables of all student groups to get this data, but because some lectures are held in more than one student group and these sometimes differ in the weeks they are taught, I compare them with each other. If the compared ones only differ in certain values, I add the values from the second object to the first object and delete the second object. That's why.
The errors when deleting while in .each-loop: When using the Rails Hash.diff method, I got something like "Cannot convert Symbol to Integer". Turns out there was suddenly an Integer value of 16 in the array, although I tested before the loop that there are only hashes in the array...
Debugging is really hard if you have 9000 hashes.
EDIT:
Sample Data:
lectures = [ {:day=>0, :weeks=>[11, 12, 13, 14], :begin=>"07:30", :end=>"09:30", :rooms=>["Li201", "G221"], :name=>"TestSubject1", :kind=>"Vw", :lecturers=>["WALDM"], :tut_groups=>["11INM"]},
{:day=>0, :weeks=>[11, 12, 13, 14], :begin=>"07:30", :end=>"09:30", :rooms=>["Li201", "G221"], :name=>"TestSubject1", :kind=>"Vw", :lecturers=>["WALDM"], :tut_groups=>["11INM"]} ]

You mean something like this?
cleaned_lectures = lectures.combination(2).reject{|first, second| some_condition}

Related

Ruby 2D Extracting Information

I am relatively new to coding and am learning ruby right now. I came across a problem where I have a huge data record (>100k record) consisting of unique ID and another consisting of the date of birth. So it's basically a 2D array. How do I go about creating a method such that every time when I key in method(year), it will give me all the unique ID of those born in the year i choose? And how do I loop this?
The method I tried doing is as follow:
def Id_with_year(year)
emPloyee_ID_for_searching_year = [ ]
employeelist.sort_by!{|a,b|b}
if employeelist.select{|a,b| b == year}.map{|a,b| a}
return emPloyee_ID_for_searching_year
end
end
I should point out that the ID are sorted. That's why I am trying to sort the year in this method so that it will give me all the ID for the year I key in. The output I had was that it returned me [ ] with nothing inside instead of the ID.
Sidenote: methods in ruby are to be named in snake case (this is not mandatory, though.)
The problem you experience is you return what was never changed. The below should work:
def id_with_year(year)
employeelist.sort_by(&:last) # sorting by last element of array
.select{|_,b| b == year} # select
.map(&:first) # map to the first element
end

SQlite 3 Ruby can only add one column of data

This is driving me insane!! I have a number of arrays which I want to put into an SQLite database. Each time I run my code it only puts in the first array in and then all the rest get "Null" I can change the order of the arrays but regardless of the array the first one always goes in but the rest don't
Here is my code, to set up the database
require 'sqlite3'
DBNAME= 'resultsdb.sqlite'
File.delete(DBNAME) if File.exists?DBNAME
$db= SQLite3::Database.new(DBNAME)
$db.execute("Create TABLE althete (date, event, pos, array1, array2, array3, agecat, gender, genderposition, array4, array5, array6)")
Here is the code to insert the arrays,
$positions.each do |position|
$db.execute("INSERT INTO althete (pos) VALUES ('#{position}')")
end
$events.each do |event|
$db.execute("INSERT INTO althete (array1) VALUES ('#{event}')")
end
And I have similar statements for the ten other arrays that I would like to go into the same table.
Sorry, my code is probably very sloppy as I am still learning ruby, any help would be most appreciated.

How to recurse through arrays in Ruby

I'm trying to use the two following methods to recursively traverse arrays of arrays until the bottom and then come back up with the match results.
You know how in a tennis tournament they start with 32 matches and pair by pair the winner moves ahead, and at the end there's only one winner? That's what I want to replicate in Ruby.
I created a match_winner that always returns the first array for the sake of simplicity. Then, I send the whole tournament array into winner that calls itself recursively until it finds a simple array corresponding to a single match.
def match_winner(array_of_arrays)
return array_of_arrays[0]
end
def winner(tournament)
if tournament[0][0].is_a?(String)
return match_winner(tournament)
else
tournament.each{|e|
winner(e)
}
end
end
tournament = [
[["one", "two"],["three", "four"]],
[["five", "six"],["seven", "eight"]]
]
puts winner(tournament).inspect
Which outputs:
[[["one", "two"], ["three", "four"]], [["five", "six"], ["seven", "eight"]]]
I tried different permutations and variations on this algorithm but I couldn't make it work correctly and return only the final winner.
Does anyone see anything obviously wrong here?
Now I'm calling winner.
I know that the question looks like it's answered, but I just did the same problem and I have to say that simply changing each to map didn't work for me, because, as the code posted, the result is an array of the first-round winners. What worked for me is:
def winner(tournament)
if tournament[0][0].is_a?(String)
return match_winner(tournament)
else
tournament.map!{|e| #use map!, because we need to apply winner() to new values
e=winner(e) #assign new value somewhere, so recursion can climb back
}
end
end
Maybe more experienced developers can explain why that is. Without these two tips it won't work.
And yes, I know "bang" is a bad coding style, danger danger high voltage, but it's my second day with Ruby and I wanted to get this to work.
And, to understand recursion, you have to understand recursion.
Looks like you want map, not each, and, as a commenter above notes, you didn't call winner in the above code.
When you call:
tournament.each {...}
that method actually returns the tournament, which is thus what winner returns.
What you want is to replace it with
tournament.map {...}
which returns a new array consisting of calling "winner" on each element of tournament.
Assuming you have 2^n number of games always and match_winner works ok:
def winner(game)
if game[0][0][0] == game[0][0][0][0]
match_winner( [ game[0], game[1] ] )
else
match_winner( [winner(game[0]), winner(game[1])] )
end
end

How do you modify array mapping data structure resultant from Ruby map?

I believe that I may be missing something here, so please bear with me as I explain two scenarios in hopes to reconcile my misunderstanding:
My end goal is to create a dataset that's acceptable by Highcharts via lazy_high_charts, however in this quest, I'm finding that it is rather particular about the format of data that it receives.
A) I have found that when data is formatted like this going into it, it draws the points just fine:
[0.0000001240,0.0000000267,0.0000000722, ..., 0.0000000512]
I'm able to generate an array like this simply with:
array = Array.new
data.each do |row|
array.push row[:datapoint1].to_f
end
B) Yet, if I attempt to use the map function, I end up with a result like and Highcharts fails to render this data:
[[6.67e-09],[4.39e-09],[2.1e-09],[2.52e-09], ..., [3.79e-09]]
From code like:
array = data.map{|row| [(row.datapoint1.to_f)] }
Is there a way to coax the map function to produce results in B that more akin to the scenario A resultant data structure?
This get's more involved as I have to also add datetime into this, however that's another topic and I just want to understand this first and what can be done to perhaps further control where I'm going.
Ultimately, EVEN SCENARIO B SHOULD WORK according to the data in the example here: http://www.highcharts.com/demo/spline-irregular-time (press the "View options" button at bottom)
Heck, I'll send you a sucker in the mail if you can fill me in on that part! ;)
You can fix arrays like this
[[6.67e-09],[4.39e-09],[2.1e-09],[2.52e-09], ..., [3.79e-09]]
that have nested arrays inside them by using the flatten method on the array.
But you should be able to avoid generating nested arrays in the first place. Just remove the square brackets from your map line:
array = data.map{|row| row.datapoint1.to_f }
Code
a = [[6.67e-09],[4.39e-09],[2.1e-09],[2.52e-09], [3.79e-09]]
b = a.flatten.map{|el| "%.10f" % el }
puts b.inspect
Output
["0.0000000067", "0.0000000044", "0.0000000021", "0.0000000025", "0.0000000038"]
Unless I, too, am missing something, your problem is that you're returning a single-element array from your block (thereby creating an array of arrays) instead of just the value. This should do you:
array = data.map {|row| row.datapoint1.to_f }
# => [ 6.67e-09, 4.39e-09, 2.1e-09, 2.52e-09, ..., 3.79e-09 ]

How do I find a integer/max integer in an array for ruby and return the indexed position?

This is what I have so far
ages = [20,19,21,17,31,33,34]
names = [Bob, Bill, Jill, Aimee, Joe, Matt, Chris]
How do I take ages and apply a method to it to extract the largest integer out of it and learn its indexed position. The reason being I want to know which person in names is the oldest. Parallel assignment is blocking my ability to do a .sort on the array becasue it changes the position of element associted with names.
Please include code to mull over thanks,
ages.zip(names).max
names[ages.index(ages.max)]
What it does is find the maximum value in ages (ages.max), get the index of the first matching value in ages, and use it to get the corresponding person. Note that if two or more people have the same age which is the maximum, it'll only give you the name of the first one in the array.
Edit: To address your comment, I'm not sure why you need this parallel arrays structure (it'd be much easier if you just had a person object). Nevertheless, you can try something like:
indices = []
ages.each_with_index { |age, i| indices << i if age < 20 }
indices.each { |i| puts names[i] }

Resources