How can I generate new variables?

K

Kyle X.

Hello, this is not so much a sketchup question as a Ruby one that I
cannot figure out. What I am trying to do is create new variables that
all have the same base name then add a number to make a series of
variables named like wall1, wall2, wall3, ect.

What I am trying to do is take an array, lets call it originalarray,
which has say 64 objects in it, and create 8 smaller arrays from this.
So array1 would be orginalarray[0-7], array2 would be
originalarray[8-15], and so on for 8 new arrays. The problem is I do not
know the length of the original array, as it is being populated by data
from an xml sheet, but I know the multiple of how it is being created,
ie by multiples of 8.

I have been trying to do this using loops doing something like:

n=0
while n != originalarray.length/8
n=n.to_s
array+n=originalarray[0..7]
n=n.to_i
n=n+1
end



I realize that is doesn't work at all in that you cannot make variables
like this, I am just trying to give a better picture of what my goal is.
So I am wondering is it possible to accomplish this at all, and if so
how? Or is there a much easier way to do this using classes or some
other method to accomplish the same goal?

Any help would be greatly appreciated. Thank you in advance for your
time.
 
7

7stud --

Kyle X. wrote in post #990090:
Hello, this is not so much a sketchup question as a Ruby one that I
cannot figure out. What I am trying to do is create new variables that
all have the same base name then add a number to make a series of
variables named like wall1, wall2, wall3, ect.

That is a typical beginner question. You NEVER need to do that. All
computer languages have arrays for that purpose.

What I am trying to do is take an array, lets call it originalarray,
which has say 64 objects in it, and create 8 smaller arrays from this.
So array1 would be orginalarray[0-7], array2 would be
originalarray[8-15], and so on for 8 new arrays. The problem is I do not
know the length of the original array, as it is being populated by data
from an xml sheet, but I know the multiple of how it is being created,
ie by multiples of 8.

I have been trying to do this using loops doing something like:

n=0
while n != originalarray.length/8
n=n.to_s
array+n=originalarray[0..7]
n=n.to_i
n=n+1
end



I realize that is doesn't work at all in that you cannot make variables
like this, I am just trying to give a better picture of what my goal is.
So I am wondering is it possible to accomplish this at all, and if so
how?

Using arrays. An array can contain anything--including other arrays:


require 'enumerator' #not necessary in ruby 1.9

master_arr = []
data = [1, 2, 3, 4, 5, 6, 7, 8]

data.each_slice(3) do |sub_arr|
master_arr << sub_arr
end

p master_arr

--output:--
[[1, 2, 3], [4, 5, 6], [7, 8]]
 
K

Kyle X.

First off thank you for the reply, and as you can probably tell I am
very novice at ruby ><. However I am running into a few issues with
this.
Using arrays. An array can contain anything--including other arrays:


require 'enumerator' #not necessary in ruby 1.9

master_arr = []
data = [1, 2, 3, 4, 5, 6, 7, 8]

data.each_slice(3) do |triplet|
master_arr << triplet
end

p master_arr

--output:--
[[1, 2, 3], [4, 5, 6], [7, 8]]

I am writing this for SketchUP so I am using Ruby 1.8.6 and am having an
issue with require 'enumerator', as it does not exist in their library
as far as I can tell --- in turn the "each_slice" command does not
function.

I was wondering if you could help me understand this command better as
well. "data.each_slice(3) do |triplet|" The "(3)" here means slice
after 3 entries in data correct? The word triplet used, is this word
required or could it be any word as long as it is consistent below i.e.
: do |x| master_arr << x? Sorry for the basic question, but I just
want to clarify.
The names of the arrays are:

master_arr[0]
master_arr[1]
master_arr[2]

Voila! But in ruby, you rarely need to refer to index positions in an
array because you can do this:

master_arr.each do |arr|
p arr
end

--output:--
[1, 2, 3]
[4, 5, 6]
[7, 8]

Or this:

master_arr.each do |arr|
new_arr = arr.map do |element|
element * 2
end

p new_arr
end

--output:--
[2, 4, 6]
[8, 10, 12]
[14, 16]

The rest I think I have figured out, but still not 100% on the map
function.

Thank you again for your time.
 
G

Gunther Diemant

[Note: parts of this message were removed to make it a legal post.]

2011/3/31 Kyle X. said:
I am writing this for SketchUP so I am using Ruby 1.8.6 and am having an
issue with require 'enumerator', as it does not exist in their library
as far as I can tell --- in turn the "each_slice" command does not
function.

Then you must write your own version. For example
def slice(array, chunk_size)
result = []
array.each_with_index do |element, index|
result << [] if index % chunk_size == 0
result.last << element
end

result
end

arr = [1,2,3,4,5,6]
slice(arr,2) #=> [[1,2],[3,4],[5,6]]

I was wondering if you could help me understand this command better as
well. "data.each_slice(3) do |triplet|" The "(3)" here means slice
after 3 entries in data correct? The word triplet used, is this word
required or could it be any word as long as it is consistent below i.e.
: do |x| master_arr << x? Sorry for the basic question, but I just
want to clarify.

Your right. You can call the thing triplet, x or chunky_bacon. Its just a
name for a local variable.
 
R

Robert Klemme

First off thank you for the reply, and as you can probably tell I am
very novice at ruby ><. However I am running into a few issues with
this.
Using arrays. =A0An array can contain anything--including other arrays:


require 'enumerator' =A0#not necessary in ruby 1.9

master_arr =3D []
data =3D [1, 2, 3, =A04, 5, 6, =A07, 8]

data.each_slice(3) do |triplet|
=A0 master_arr << triplet
end

p master_arr

--output:--
[[1, 2, 3], [4, 5, 6], [7, 8]]

I am writing this for SketchUP so I am using Ruby 1.8.6 and am having an
issue with require 'enumerator', as it does not exist in their library
as far as I can tell --- in turn the "each_slice" command does not
function.

You can easily cook it yourself

module Enumerable
def each_slice(n)
a =3D []

each do |x|
a << x

if a.size =3D=3D n
yield a
a.clear
end
end

yield a unless a.empty?
self
end
end
I was wondering if you could help me understand this command better as
well. =A0"data.each_slice(3) do |triplet|" =A0The "(3)" here means slice
after 3 entries in data correct?
Correct.

=A0The word triplet used, is this word
required or could it be any word as long as it is consistent below i.e.
: =A0do |x| master_arr << x? =A0Sorry for the basic question, but I just
want to clarify.

Yes, it's the name of the block argument. You can name it anyway you
like. You should only avoid reusing a name used outside the block in
order to avoid confusion and incompatibility should the program be
executed on 1.9 at one day.

You can even use three names!

irb(main):041:0> Array.new(10) {|idx| idx}
=3D> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
irb(main):042:0> Array.new(10) {|idx| idx}.each_slice(3)
{|first,second,third| p first}
0
3
6
9
=3D> nil
The rest I think I have figured out, but still not 100% on the map
function.

Enumerable#map sends all values through a conversion function and
collects them in a new Array:

irb(main):043:0> Array.new(10) {|idx| idx}.map {|x| x + 100}
=3D> [100, 101, 102, 103, 104, 105, 106, 107, 108, 109]

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
K

Kyle X.

Thank you all very much for your responses. Both solutions work great.
Thanks again.
 
7

7stud --

Kyle X. wrote in post #990113:
First off thank you for the reply, and as you can probably tell I am
very novice at ruby >

No problem--that's what this forum is for.
require 'enumerator' #not necessary in ruby 1.9

master_arr = []
data = [1, 2, 3, 4, 5, 6, 7, 8]

data.each_slice(3) do |triplet|
master_arr << triplet
end

p master_arr

--output:--
[[1, 2, 3], [4, 5, 6], [7, 8]]

I am writing this for SketchUP so I am using Ruby 1.8.6 and am having an
issue with require 'enumerator', as it does not exist in their library
as far as I can tell

I'm using ruby 1.8.6 too, and the Enumerator module is part of the ruby
standard library. Are you sure you spelled it right? But if it's not
provided, it's not provided.

I was wondering if you could help me understand this command better as
well. "data.each_slice(3) do |triplet|" The "(3)" here means slice
after 3 entries in data correct?

Yes, the each_slice() method allows you to chop up an array into chunks
of the specified size.
The word triplet used, is this word
required or could it be any word as long as it is consistent below i.e.
: do |x| master_arr << x? Sorry for the basic question, but I just
want to clarify.

'triplet' is just a descriptive variable name. It is a "block
parameter" which is just like a method parameter:

def do_stuff(x) #x is a method parameter
x+2 #or you can explicitly write: return x+2
end

answer = do_stuff(5)
puts answer #=> 7


Ruby uses blocks everywhere. Here is a simple example:

words = ["hello", "world", "goodbye"]

words.each do |word|
puts word
end

--output:--
hello
world
goodbye

The each() method sends each element of the array to the block, which is
this part:

do |word|
puts word
end

'do' signals the start of a block. What happens is that ruby calls the
block, which is like a method with, for each element of the array. In
my example, the element of the array is assigned to the variable named
'word', and then inside the block you can do whatever you want to the
word variable.

The map() function, like each(), tells ruby to send each element of the
array to the block. However, map() also *takes the return value of the
block* and shoves it into a new array:


words = ["hello", "world", "goodbye"]

new_arr = words.map do |x|
1
end

p new_arr

--output:--
[1, 1, 1]

In that example, the block returns 1 for every element of the array.
But you can use map to do more useful things--like capitalize all the
words in the array:

words = ["hello", "world", "goodbye"]

new_arr = words.map do |x|
x.capitalize #same as: 'return x.capitalize'
end

p new_arr

--output:--
["Hello", "World", "Goodbye"]

So whenever, you want to do something to every member of an array, map()
is a good choice.
 
R

Robert Klemme

Dear 7stud,

Thank you for the very clear descriptions. =A0Your examples are much more
helpful than the examples I find in places like -
http://www.germane-software.com/software/rexml/doc/index.html

But that is about REXML and not general iteration of collections in
Ruby. For REXML: did you look at the tutorial?
http://www.germane-software.com/software/rexml/docs/tutorial.html

Cheers

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top