I'm working my way through an online program learning Ruby and one of the challenges/lessons was to write a method that takes in an argument of a hash whose values are all numbers and returns the "key" corresponding to the lowest value.
I wrote the following code that passed the test and afterward was shown the "recommended" solution, which of course was much more efficient. Can someone walk me through the second version of the method below and tell me how it accomplishes the task?
For purposes of the challenge, I was not allowed to use any of the following methods:
$getCrimes = mysql_query("SELECT * FROM crimes ORDER BY crimeid ASC");
$thepost = $_POST['crimeid'];
if ($_POST['commit']) {
$crimethingy = $_POST['crimeid'];
$getArray = mysql_fetch_array(mysql_query("SELECT * FROM crimes WHERE crimeid = '$thepost'"));
$theID = $getArray['crimeid'];
$theName = $getArray['crimename'];
if ($crimethingy > 0) {
echo $theName;
}
}
while ($crimeRows = mysql_fetch_array($getCrimes)) {
$crime_id = $_POST['crimeid'];
$crimeID = $crimeRows['crimeid'];
$crimeName = $crimeRows['crimename'];
$lowestPayout = $crimeRows['payoutlow'];
$highestPayout = $crimeRows['payouthigh'];
echo
"
<table cellpadding='2' cellspacing='1' width='75%' class='content-cell' align='center' style='margin-top: 5px; margin-bottom: 5px;'>
<tr><td class='header'>Avaliability</td></tr>
<tr><td class='content' style='height: 50px;'>
<i style='font-size: 13px;'><center>$crimeName</center></i>
<br>
<i style='font-size: 11px;'><center>£$lowestPayout - £$highestPayout</center></i>
</td></tr>
<tr><td class='header'><input type='hidden' name='crimeid' value='$crimeID'>
<input type='submit' name='commit' value='Commit' style='width: 100%' class='submit'></td></tr>
</table>
";
}
My solution:
#keys
#values
#min
#sort
#min_by
Recommended solution:
def key_for_min_value(name_hash)
lowest_key = nil
if name_hash != {}
value_array=name_hash.collect do |key,value|
value
end
loop do
swapped = false
(value_array.length-1).times do |i|
if value_array[i] > value_array[i+1]
value_array[i], value_array[i+1] = value_array[i+1], value_array[i]
swapped=true
end
end
break if not swapped
end
name_hash.each do |key,value|
if value == value_array.first
lowest_key = key
end
end
end
lowest_key
end
答案 0 :(得分:2)
The second solution works because your hash can't contain a value that is greater than Float::INFINITY so it's guaranteed to trigger the strUser === "5"
condition at least once.
An alternative would be to set if
and then in the condition do
lowest_value = nil
but it's not as elegant (and requires another check that will only be true the first iteration.
Another alternative would be to remove the first value in the hash and set that to if lowest_value.nil? || v < lowest_value
, then loop through the rest.