There has got to be a more elegant solution than this. Suppose I have
2 identical length arrays that I want to add together to produce a
third array. The best solution I've come up with is:
On Sep 10, 2008, at 10:42 AM, Patrick Doyle wrote:
There has got to be a more elegant solution than this. Suppose I have
2 identical length arrays that I want to add together to produce a
third array. The best solution I've come up with is:
There has got to be a more elegant solution than this. Suppose I have
2 identical length arrays that I want to add together to produce a
third array. The best solution I've come up with is:
c = (0...a.size).map {|i| a[i] + b[i]}
Any suggestions?
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama
There has got to be a more elegant solution than this. Suppose I have
2 identical length arrays that I want to add together to produce a
third array. The best solution I've come up with is:
Arrghh!
I looked at zip and, for some reason completely missed the fact that
it constructs an array of arrays. For some reason, I decided that it
simply interweaved the two arrays. That's what I was looking for.
c = Array.new(a.size){|i| a[i] + b[i]}
the second is far more efficient for large arrays - in terms of memory.
Yeah, that's probably what I would do for a simple script. I haven't
checked memory usage, but it is elegant IMHO. Probably best for very
large arrays.
a = 1, 2, 3, 4
b = 4, 3, 2, 1
(Matrix[a] + Matrix[b]).to_a.flatten
=> [5, 5, 5, 5]
Todd
···
On Thu, Sep 11, 2008 at 2:02 PM, Peter Bunyan <peter.bunyan@gmail.com> wrote:
Patrick Doyle wrote:
There has got to be a more elegant solution than this. Suppose I have
2 identical length arrays that I want to add together to produce a
third array. The best solution I've come up with is:
I just ran into a similar problem, and I thought it fits into this
thread.
The Vector class defines the collect2() and collect2!() methods, which
conceptually I like very much. So I thought I could just use the same
concept and extend Array like this:
class Array
def collect2(v) # :yield: e1, e2
Array.Raise ErrDimensionMismatch if size != v.size
(0 .. size - 1).collect do
>i>
yield self[i], v[i]
end
end
def collect2!(v) # :yield: e1, e2
Array.Raise ErrDimensionMismatch if size != v.size
(0 .. size - 1).collect do
>i>
self[i] = yield self[i], v[i]
end
end
end
After this I can simply do:
a = [1,2,3]
b = [4,5,6]
a.collect2(b){|e1,e2| e1+e2}
=> [5, 7, 9]
Does anybody see anything wrong with this?
If not, it seems such a handy concept that I'm surprised these are not
standard methods of Array. I've had this problem in various forms over
the past and typically reverted to Array#each_index, always thinking
that this is too clumsy for Ruby, but until now I never took the time to
come up with something more elegant (not that I want to take any credit
for this suggestion as I simply copied what's already in Vector).
Todd Benson wrote:
···
On Thu, Sep 11, 2008 at 2:02 PM, Peter Bunyan <peter.bunyan@gmail.com> > wrote:
Yeah, that's probably what I would do for a simple script. I haven't
checked memory usage, but it is elegant IMHO. Probably best for very
large arrays.
a = 1, 2, 3, 4
b = 4, 3, 2, 1
(Matrix[a] + Matrix[b]).to_a.flatten
Everything in Ruby is a pointer. If a[0] is a pointer to a "big long
string", then a.zip(b)[0][0] is a pointer to the very same "big long
string" - not a copy of the string. So creating the "huge_new_array"
just creates some new pointers, right? And pointers are very small. So
for huge_new_array to be a problem, the existence of a and b would have
to have been problematic to start with - meaning that they would have to
have huge length. The amount of *data* in the story (stuff like "big
long string") is not increased.
Everything in Ruby is a pointer. If a[0] is a pointer to a "big long
string", then a.zip(b)[0][0] is a pointer to the very same "big long
string" - not a copy of the string. So creating the "huge_new_array"
just creates some new pointers, right? And pointers are very small. So
for huge_new_array to be a problem, the existence of a and b would have
to have been problematic to start with - meaning that they would have to
have huge length. The amount of *data* in the story (stuff like "big
long string") is not increased.
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama
Everything in Ruby is a pointer. If a[0] is a pointer to a "big long
string", then a.zip(b)[0][0] is a pointer to the very same "big long
string" - not a copy of the string. So creating the "huge_new_array"
just creates some new pointers, right? And pointers are very small. So
for huge_new_array to be a problem, the existence of a and b would have
to have been problematic to start with - meaning that they would have to
have huge length. The amount of *data* in the story (stuff like "big
long string") is not increased.
Definitely relevant, too, since the block form is quite sufficient for
the OP's original purpose (and similar stuff where the goal is to
process one array in the light of another); thx for bringing out that
point. m.
···
ara.t.howard <ara.t.howard@gmail.com> wrote:
On Sep 10, 2008, at 1:45 PM, Joel VanderWerf wrote:
> It's less dramatic when the entries are not nil (or fixnum etc)--I
> think that's Matt's point.
>
> mb = 2 ** 20
>
> big = 2 * mb
>
> a = Array.new big do |i| "the string for entry #{i}" end
> b = a.dup
>
> memory_usage = `ps -o rss= -p #{Process.pid}`.to_i
> puts memory_usage
>
> a.zip(b)
>
> memory_usage = `ps -o rss= -p #{Process.pid}`.to_i
> puts memory_usage
>
> __END__
> 213256
> 322232
true enough - my point is that the block form is much better when the
arrays are big, without it the new array, pointers or not, is created.