Add outside variable to array elements

Hi,

I have all of six hours of programming experience, so I hope that
you’ll bear with me. Ain’t all that comfortable with terminology and
such.

I opened a binary file called “16bytes” and read it into a string. Then
I unpacked the string into an array of Short Integers. At least that’s
what I assume that I did.

What I’d like to do is add an outside variable via the keyboard to each
element in the array.

Okay, I’ll admit that I barely understood what I’ve written so far, but
I think it’s correct. Burst my bubble, if you like. It won’t hurt my
feelings too much.

Here’s the code:

whole_file = open(‘16bytes’, ‘rb’) { |f| f.read}
ar1 = whole _file.unpack(‘S*’)

puts(‘Enter an increase value’)
incVal=gets.chomp
incVal.to_i

ar2 = ar1.collect { |x| x + incVal}
puts ar2

I assume the thing doesn’t work because incVal is outside of the curly
brace doo-dad. It wouldn’t surprise me if there’s other problems, too.

Go nuts with the constructive criticism.

So how can a person add a user-entered number to each value in an array
like this?

Thanks.

On 23 Aug 2007, at 11:18, Ignatz H. wrote:

whole_file = open(‘16bytes’, ‘rb’) { |f| f.read}
ar1 = whole _file.unpack(‘S*’)

puts(‘Enter an increase value’)
incVal=gets.chomp
incVal.to_i

This should be incVal = incVal.to_i. String#to_i returns the
integer your String represents it does not convert the String object
into an Integer.

ar2 = ar1.collect { |x| x + incVal}
puts ar2

There are some typos like the space in ‘whole _file’, but I assume
those are just typos (use cut&paste). You don’t say what error(s) you
get, so it is hard to say what your problem is apart from the
incVal.to_i part.

Alex G.

Bioinformatics Center
Kyoto University

From: Ignatz H. [mailto:[email protected]]

Go nuts with the constructive criticism.

rubyists don’t criticize, they just fade away :slight_smile:

my simple advice: run your code a line at a time in irb

kind regards -botp

Thank you, Alex G…

incVal = incVal.to_i worked just as you suspected it would.

And thank you, botp, for the irb suggestion.

My apologies for the typos, as well as for not supplying error messages.
The computer I was using at the time didn’t have Ruby, so I had to rely
on my faulty memory. The vodka probably didn’t help matters much.

I’ve done some more reading, and I’m a little embarrassed at having
called a code block a “curly brace doo-dad.”

BTW, I couldn’t find anything about cut&paste in the Core API
documentation.

I have this code now:

whole_file = open(‘16bytes’, ‘rb’) { |f| f.read}
ar1 = whole_file.unpack(‘S*’)

puts(‘Enter an increase value’)
incVal=gets.chomp
incVal = incVal.to_i

ar2 = ar1.collect { |x| x + incVal}

ar2= ar2.pack(‘S*’)

open(‘output’,‘wb’){|f| f.write ar2}

But there’s a problem with this. If, for instance, ‘16bytes’ contained
the Short 65535 and incVal=12, the result would be 65547. That’s too
big to store as a Short. The 65547 wraps over to 11 when it gets saved
in ‘output’.

Is there any way to iterate over an array and apply a conditional like
if x < 45000 then x = x + incVal
rather than having everything in the array get incVal added to it? I
doubt that I’ll ever have an incVal over 20000.

PS I was joking about cut&paste.

Peña, Botp wrote:

ar2 = ar1.collect { |x| x<45000 ? (x + incVal) : x}

or
ar2 = ar1.collect { |x| if x<45000 then (x + incVal) else x end}
or
ar2 = ar1.select{|x| x<45000}.collect{|x| x + incVal}

i usually prefer the last one, since i think like: “select those
elements < 45000, then with those collections, increment each”. but that
is just me.

welcome to ruby.
kind regards -botp

The last one is not equivalent to the other two. It will drop values >=
45000.

Regards
Stefan

On 8/25/07, Stefan R. [email protected] wrote:

welcome to ruby.
kind regards -botp

The last one is not equivalent to the other two. It will drop values >=
45000.

oops. mea culpa. what was i thinking again :frowning: yes, pls ignore the
last one. at least i may be right on the testing part :))
kind regards -botp

Thanks, guys.
I’ll try to ask more intelligent questions in the future.

From: Ignatz H. [mailto:[email protected]]

whole_file = open(‘16bytes’, ‘rb’) { |f| f.read}

ar1 = whole_file.unpack(‘S*’)

puts(‘Enter an increase value’)

incVal=gets.chomp

incVal = incVal.to_i

2 lines above can be merged like,

incVal = gets.to_i

ar2 = ar1.collect { |x| x + incVal}

ar2= ar2.pack(‘S*’)

open(‘output’,‘wb’){|f| f.write ar2}

Is there any way to iterate over an array and apply a conditional like

if x < 45000 then x = x + incVal

refer back to the line containing

ar2 = ar1.collect { |x| x + incVal}

change it to any of the ff (pls test all)

ar2 = ar1.collect { |x| x<45000 ? (x + incVal) : x}

or
ar2 = ar1.collect { |x| if x<45000 then (x + incVal) else x end}
or
ar2 = ar1.select{|x| x<45000}.collect{|x| x + incVal}

i usually prefer the last one, since i think like: “select those
elements < 45000, then with those collections, increment each”. but that
is just me.

welcome to ruby.
kind regards -botp