Yielding a modified Ruby array to a block - arrays

I'm trying to turn 2 lines of ruby code into 1. For example:
def average(numbers)
result = numbers.compact
numbers.reduce(+) / numbers.length
end
I've been looking through array methods and can't find an appropriate one to turn this function into a one-liner. I had hoped something like this would work:
def average(numbers)
numbers.compact.<tap or another method> { |arr| arr.reduce(+) / arr.length }
end
Basically, I'm modifying the array (in the example I have to call compact to rid nil values), so I don't have access to the array variable, and I don't want an iterator, because I don't want to call reduce(+) and length on individual elements of the array.
Does anyone have an idea of methods I could look into?

I believe you mean for your method to be the following (reduce(:+), not reduce(+) and use result rather than numbers in the second line).
def average(numbers)
result = numbers.compact
result.reduce(:+) / result.length
end
average [1,2,3]
#=> 2
If you wish the average to be a float, change the second line to
result.reduce(0.0, :+) / result.length
There are various ways to combine the two lines of the method, but I don't prefer any of them to the above. Here are a few. (I don't see how Object#tap could be used here.)
numbers.compact.reduce(:+) / numbers.compact.length
(result = numbers.compact).reduce(:+) / result.compact.length
numbers.map(&:to_i).reduce(:+) / numbers.compact.length
Note that, even if numbers can be mutated, one cannot write
numbers.compact!.reduce(:+) / numbers.length
because numbers.compact! returns nil if numbers contains no nil elements.
In Ruby v2.4+ you can use Array#sum:
result.sum / result.length

You could change the way you call average
def average(numbers)
numbers.reduce(:+) / numbers.length
end
average(num_array.compact)

Related

how to sum only the max value for common prefix inside the array in scala

I have array contain string items in scala , each item contain from prefix + || + double value like below :
var y = Array("Zara||6.0", "Nuha||4.0","Zara||2.0","Zara||0.1")
what I want to Do :
i need sum all double value from above array (y(i).split("\|\|")(1)) But if the prefix the duplicated in the array then I only want sum the max value like below :
for item Zara we have 3 values i want to take the max (in our sample it 6.0)
for item Nuha it unique then i will take it's value (4.0)
the excepted output is (6.0+4.0)=10.0
is there are any way to do it in scala rather than using 2 instead loop ?
Prepare your array: extract prefix and values into tuple. Use foldLeft for aggregate max elem for each prefix, and sum values
val res = y.map(_.split("\\|\\|")).map(arr => (arr(0), arr(1).toDouble))
.foldLeft(Map.empty[String, Double]) { (acc, elem) =>
val value = acc.get(elem._1).map(math.max(_, elem._2)).getOrElse(elem._2)
acc + (elem._1 -> value)
}.values.sum
println(res)
You can do it pretty much in one step (it's three steps technically, but only one specifically addressing your requirement, everything else (split and sum) is kinda a given either way.
y
.iterator
.map(_.split("""\|\|"""))
.groupMapReduce(_.head)(_.last.toDouble)(_ max _)
.values
.sum
Also ... do not use vars. Even if you just putting together a quick sample. Vars are evil, just pretend they do not exist at all ... at least for a while, until you acquire enough of a command of the language to be able to tell the 1% of situations, where you might actually need them. Actually, avoid using Arrays as much as possible too.

Optimizing custom fill of a 2d array in Julia

I'm a little new to Julia and am trying to use the fill! method to improve code performance on Julia. Currently, I read a 2d array from a file say read_array and perform row-operations on it to get a processed_array as follows:
function preprocess(matrix)
# Initialise
processed_array= Array{Float64,2}(undef, size(matrix));
#first row of processed_array is the difference of first two row of matrix
processed_array[1,:] = (matrix[2,:] .- matrix[1,:]) ;
#last row of processed_array is difference of last two rows of matrix
processed_array[end,:] = (matrix[end,:] .- matrix[end-1,:]);
#all other rows of processed_array is the mean-difference of other two rows
processed_array[2:end-1,:] = (matrix[3:end,:] .- matrix[1:end-2,:]) .*0.5 ;
return processed_array
end
However, when I try using the fill! method I get a MethodError.
processed_array = copy(matrix)
fill!(processed_array [1,:],d[2,:]-d[1,:])
MethodError: Cannot convert an object of type Matrix{Float64} to an object of type Float64
I'll be glad if someone can tell me what I'm missing and also suggest a method to optimize the code. Thanks in advance!
fill!(A, x) is used to fill the array A with a unique value x, so it's not what you want anyway.
What you could do for a little performance gain is to broadcast the assignments. That is, use .= instead of =. If you want, you can also use the #. macro to automatically add dots everywhere for you (for maybe cleaner/easier-to-read code):
function preprocess(matrix)
out = Array{Float64,2}(undef, size(matrix))
#views #. out[1,:] = matrix[2,:] - matrix[1,:]
#views #. out[end,:] = matrix[end,:] - matrix[end-1,:]
#views #. out[2:end-1,:] = 0.5 * (matrix[3:end,:] - matrix[1:end-2,:])
return out
end
For optimal performance, I think you probably want to write the loops explicitly and use multithreading with a package like LoopVectorization.jl for example.
PS: Note that in your code comments you wrote "cols" instead of "rows", and you wrote "mean" but take a difference. (Not sure it was intentional.)

Create Enumerable In Place Slice Of Array in Ruby

I'm looking to find a way to take an array in ruby, two indices in that array and return an enumerable object which will yield, in order, all the elements between and including the two indices. But for performance reasons, I want to do this subject to the following two conditions:
This slice to enum does not create a copy of the subarray I want a return an enum over. This rules out array[i..j].to_enum, for example because array[i..j] is creating a new array.
It's not necessary to loop over the entire array to create the enum.
I'm wondering if there's a way to do this using the standard library's enumerable or array functionality without having to explicitly create my own custom enumerator.
What I'm looking for is a cleaner way to create the below enumerator:
def enum_slice(array, i, j)
Enumerator.new do |y|
while i <= j
y << array[i] # this is confusing syntax for yield (see here: https://ruby-doc.org/core-2.6/Enumerator.html#method-c-new)
i += 1
end
end
end
That seems pretty reasonable, and could even be turned into an extension to Array itself:
module EnumSlice
def enum_slice(i, j)
Enumerator.new do |y|
while i <= j
y << self[i]
i += 1
end
end
end
end
Now within the Enumerator block, y represents a Proc you call when you have more data. If that block ends it's presumed you're done enumerating. There's no requirement to ever terminate, an infinite Enumerator is allowed, and in that case it's up to the caller to stop iterating.
So in other words, the y block argument can be called zero or more times, and each time it's called output is "emitted" from the enumerator. When that block exits the enumerator is considered done and is closed out, y is invalid at that point.
All y << x does is call the << method on Enumerator::Yielder, which is a bit of syntactical sugar to avoid having to do y.call(x) or y[x], both of which look kind of ugly.
Now you can add this to Array:
Array.include(EnumSlice)
Where now you can do stuff like this:
[ 1, 2, 3, 4, 5, 6 ].enum_slice(2, 4).each do |v|
p v
end
Giving you the correct output.
It's worth noting that despite having gone through all this work, this really doesn't save you any time. There's already built-in methods for this. Your enum_slice(a, i, j) method is equivalent to:
a.drop(i).take(j)
Is that close in terms of performance? A a quick benchmark can help test that theory:
require 'benchmark'
Benchmark.bm do |bm|
count = 10000
a = (0..100_000).to_a
bm.report(:enum_slice) do
count.times do
a.enum_slice(50_000, 25_000).each do
end
end
end
bm.report(:drop_take) do
count.times do
a.drop(50_000).take(25_000).each do
end
end
end
end
The results are:
user system total real
enum_slice 0.020536 0.000200 0.020736 ( 0.020751)
drop_take 7.682218 0.019815 7.702033 ( 7.720876)
So your approach is about 374x faster. Not bad!

Get hash values (from a number of hashes) in an array and sum them up [duplicate]

This question already has answers here:
Sum the value of array in hash
(8 answers)
Closed 5 years ago.
I currently have an array of hashes:
total_order = [{"Hamburger"=>5.0}, {"Hamburger"=>5.0}, {"Hamburger"=>5.0}]
I'm trying to iterate over each hash in this array and then sum all of the values. So essentially I want to return 15.0.
Here is my code at the moment. I'm not even trying to sum it yet, just return each value so that I can sum it after. When I run it I only get the array returned:
def total_order_cost
total_order.each do |item|
item.map do |k, v|
print v
end
end
end
Any idea how I go about iterating over the hashes and then sum the values within? Have checked other people's questions but don't seem to be able to make any of the solutions work in my case. Other answers I have seen do not address my question and do not include solutions such as the use of flat_map.
This is the most succinct way I came up with:
2.1.2 :013 > [{a:1},{b:2}].map(&:values).flatten.inject(:+)
=> 3
values returns just the values, not the keys, as an array and then inject sums them all together. inject is a great function, and really helped me think in terms of list comprehensions, which this kinda is.
To sum the values of a hash:
{a:1,b:2}.values.sum
#=> 3
And to do that for your array of hashes:
total_order.flat_map(&:values).sum
#=> 15.0
Note that sum is only available in Ruby 2.4.0 and later (and in Rails). In older versions you can use reduce(:+) and inject(:+) instead of sum.
Your method returns the result of total_oder.each, and Array#each just returns self, so your method simply returns total_order. This is true for all implementations of each, by the way, not just for Array; it is the standard protocol for each. each is intended to be used only for the block's side-effects.
If you want to transform an Enumerable, you need to use Enumerable#map, which transforms each element using the given block.
So, you want to get all the values from the Hashes. Look at the documentation of Hash and see if you can spot a method that could possibly be used to return the values. What about Hash#values, that sounds good, doesn't it?
total_order.map(&:values)
#=> [[5.0], [5.0], [5.0]]
Now, we want to get rid of that extra level of nesting, we could use Array#flatten for that, but it is much better to make sure that the nesting doesn't occur in the first place, so we use Enumerable#flat_map instead of Enumerable#map:
total_order.flat_map(&:values)
#=> [5.0, 5.0, 5.0]
Okay, next you want to sum those values. Again, let's just look at the documentation of Enumerable. What could a method that sums the items of an Enumerable possibly be called. How does Enumerable#sum sound?
total_order.flat_map(&:values).sum
#=> 15.0
And there you have your desired result. The moral of the story is: learn the methods in Enumerable, they are the bread and butter of Ruby programming. And, learn to navigate the documentation.
sum = 0
def total_order_cost
total_order.each do |item|
item.each do |k,v|
sum = sum + v
end
p sum
end
Your code is not too far off:
total_order = [{"Hamburger"=>5.0}, {"Hamburger"=>5.0}, {"Hamburger"=>5.0}]
def total_order_cost(order)
cost = 0
order.each do |item|
item.each do |k, v|
cost = cost + v
end
end
return cost
end
puts total_order_cost(total_order) # 15.0

multiply array using each on ruby

I've been stuck on this problem. I'd appreciate any help.
The instructions
"Use the .each method on the odds array to print out double the value of each item of the array. In other words, multiply each item by 2.
Make sure to use print rather than puts, so your output appears on one line."
My code
odds = [1,3,5,7,9]
odds.each do |placeholder|
odds *= 2
print odds
end
odds = [1,3,5,7,9]
odds.each do |placeholder|
odds *= 2
print odds
end
Your usage of #each is correct here, but remember that #each receives an ::Enumerable object, the block passed in uses the variable placeholder to encapsulate the value in the ::Array at the current point of the iteration. Therefore you would need to use placeholder to retrieve the value you want to double, and not odds because odds would still be an ::Array within the ::Enumerable function #each.
This code can be written in two lines as follows:
odds = [1,3,5,7,9]
odds.each {|placeholder| print placeholder * 2 }
Strictly speaking, #map would be the preferred method for doing this.
odds.each { |x| print "#{x*2}" }
ruby-ish way:
print odds.map {|x| x*2}.join(' ')
You are trying to multiply the Array odds by two in each iteration in your code. The do |placeholder| means 'for each item in the array, give me the single element and call it placeholder'.
So you would need to use placeholder *= 2.
However, since you aren't mutating the original value in odds, you can shorten your inner block by just print placeholder * 2.
Additionally, while the question might be saying to use :each, :map is much more canonical to what you are doing. Using map would allow you to double each element like so:
odds.map{ |i| i*2 }
odds is your array. placeholder represents a value from the array. Without explicitly providing you the answer, what you want to do is multiply the value by 2, not the array itself.
Here Iam done that on succesfully
odds = [1,3,5,7,9]
odds.each do |x|
x *= 2
print x
end

Resources