Simple iteration in a function problem

i'm trying to do this, and I'm stuck

class holderOfYs

def initialize()
@ys = Array.new
end

def addX( x )
@ys << x
end

# this is the problem function. all I want is the specific (ONE)
element
# from the @ys array that matches the id, but when you iterate over the
# array, i can't find a way to only have one element returned
def getXById(id)
@ys.each_with_index do |comp, index|
   if( @ys[index].getUniqueId == id )
     @ys.fetch(index)
   end
end
end

class Y
@uniqueId

def getUniqueId
  @uniqueId
end

end

class X < Y
def getUniqueId
  super
end
end

I tried setting a variable like :
def getXById(id)
inst = X.new
@ys.each_with_index do |comp, index|
   if( @ys[index].getUniqueId == id )
     inst = @ys.fetch(index)
   end
end

inst
end

...but I'm not looking to instantiate a new X, and even that solution
seems to screw up the @ys array.

···

--
Posted via http://www.ruby-forum.com/.

Blake Miller wrote:
...

# this is the problem function. all I want is the specific (ONE)
element
# from the @ys array that matches the id, but when you iterate over the
# array, i can't find a way to only have one element returned
def getXById(id)

Instead of:

@ys.each_with_index do |comp, index|
   if( @ys[index].getUniqueId == id )
     @ys.fetch(index)
   end
end

try this:

   @ys.find {|x| x.getUniqueId == id}

···

end

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Blake Miller wrote:

# this is the problem function. all I want is the specific (ONE)
element
# from the @ys array that matches the id, but when you iterate over the
# array, i can't find a way to only have one element returned
def getXById(id)
@ys.each_with_index do |comp, index|
   if( @ys[index].getUniqueId == id )
     @ys.fetch(index)
   end
end
end

Perhaps

def getXById( id )
  @ys.detect { |y| y.getUniqueId == id }
end

See the docs for Enumerable#detect about handling what's returned if
nothing is found.

···

--
Posted via http://www.ruby-forum.com/\.

I've tried to answer your question and Rubyify your code a bit:

class YHolder
   def initialize
     @ys = Array.new
   end

   def add_y(y)
     @ys << y
   end
   alias_method :<<, :add_y

   def fetch_by_id(id)
     @ys.find { |y| y.object_id == id }
   end
   alias_method :, :fetch_by_id
end

class Y; end
class X < Y; end

holder, ids = YHolder.new, Array.new
10.times do
   new_y_or_x = [Y, X][rand(2)].new

   ids << new_y_or_x.object_id
   holder << new_y_or_x
end

p holder # show the collection

# pick one by id
pick = ids[3]
p pick
p holder[pick]

# >> #<YHolder:0x1e2928 @ys=[#<Y:0x1e289c>, #<X:0x1e2874>, #<X:0x1e284c>,
# >> #<Y:0x1e2824>, #<X:0x1e27fc>, #<Y:0x1e27d4>,
# >> #<Y:0x1e27ac>, #<X:0x1e2784>, #<X:0x1e275c>,
# >> #<Y:0x1e2734>]>
# >> 988178
# >> #<Y:0x1e2824>

__END__

Hope that helps.

James Edward Gray II

···

On Dec 1, 2006, at 12:57 PM, Blake Miller wrote:

i'm trying to do this, and I'm stuck

I tried setting a variable like :
def getXById(id)
inst = X.new
@ys.each_with_index do |comp, index|
   if( @ys[index].getUniqueId == id )
     inst = @ys.fetch(index)
   end
end

inst
end

...but I'm not looking to instantiate a new X, and even that solution
seems to screw up the @ys array.

I've also tried this:
def getXById(id)
    matchingIndx = 0
    @components.each_index do |index|
      if( @components[index].getUniqueId == uniqueId )
        matchingIndx = index
      end
    end

    @components.fetch(matchingIndx)
end

but it just returns the 0th one every time (I'm assuming there wasn't a
match)

···

--
Posted via http://www.ruby-forum.com/\.

Mike Fletcher wrote:

Blake Miller wrote:

# this is the problem function. all I want is the specific (ONE)
element
# from the @ys array that matches the id, but when you iterate over the
# array, i can't find a way to only have one element returned
def getXById(id)
@ys.each_with_index do |comp, index|
   if( @ys[index].getUniqueId == id )
     @ys.fetch(index)
   end
end
end

Perhaps

def getXById( id )
  @ys.detect { |y| y.getUniqueId == id }
end

See the docs for Enumerable#detect about handling what's returned if
nothing is found.

I don't know where "detect" comes from (@ys is an array, and it doesn't
seem to be a method of Array)? however, I tried that and the result is
null, but I know for certain that the id being searched for does match
an element in the @ys array (because I wrote a function to print out the
ids in @ys)

···

--
Posted via http://www.ruby-forum.com/\.

# pick one by id
pick = ids[3]
p pick
p holder[pick]

# >> #<YHolder:0x1e2928 @ys=[#<Y:0x1e289c>, #<X:0x1e2874>, #<X:
0x1e284c>,
# >> #<Y:0x1e2824>, #<X:0x1e27fc>, #<Y:
0x1e27d4>,
# >> #<Y:0x1e27ac>, #<X:0x1e2784>, #<X:
0x1e275c>,
# >> #<Y:0x1e2734>]>
# >> 988178
# >> #<Y:0x1e2824>

__END__

Hope that helps.

James Edward Gray II

Note: The ids are strings. The @ys.find { |y| y.object_id == id } still
isn't working for me, i also tried y.object_id.equals(id) but I can't
seem to find the darn match : /

···

--
Posted via http://www.ruby-forum.com/\.

Blake Miller wrote:

I tried setting a variable like :
def getXById(id)
inst = X.new
@ys.each_with_index do |comp, index|
   if( @ys[index].getUniqueId == id )
     inst = @ys.fetch(index)
   end
end

inst
end

...but I'm not looking to instantiate a new X, and even that solution
seems to screw up the @ys array.

I've also tried this:
def getXById(id)
    matchingIndx = 0
    @components.each_index do |index|
      if( @components[index].getUniqueId == uniqueId )
        matchingIndx = index
      end
    end

    @components.fetch(matchingIndx)
end

but it just returns the 0th one every time (I'm assuming there wasn't a
match)

You believe you are solving a specific programming problem, but in fact you
are learning how to solve programming problems.

1. Put in as many message-printing lines into your program as you need to
find out what is going on.

2. Keep adding debugging lines until the problem becomes obvious.

3. Repeat as required.

When you look at a line of code like this:

@components.each_index do |index|

      if( @components[index].getUniqueId == uniqueId )
        matchingIndx = index
      end
    end

And it doesn't deliver, what should you do? You should add lines that print
helpful messages until it is impossible not to see the problem.

First question. Is the ID in the array? Find out by printing all the array's
IDs and look at them. Is it there?

Second question. Does the variable "uniqueId" actually contain the required
ID? Find out by printing its value. It is right?

Third question. Can the comparison you are using actually produce the result
you seek? Find out by testing it with two variables that actually are
equal.

Most difficult programming problems are beaten to death in just this way.
The important things to remember are (1) the computer is breathtakingly
dumb, (2) you are smarter than the computer, but (3) successful debugging
requires you to think like the computer, as demeaning as that might seem at
first.

···

--
Paul Lutus
http://www.arachnoid.com

See the docs for Enumerable#detect about handling what's returned if
nothing is found.

I don't know where "detect" comes from (@ys is an array, and it doesn't
seem to be a method of Array)? however, I tried that and the result is
null, but I know for certain that the id being searched for does match
an element in the @ys array (because I wrote a function to print out the
ids in @ys)

Sorry, missed that "Enumerable"

···

--
Posted via http://www.ruby-forum.com/\.

Blake Miller wrote:

# pick one by id
pick = ids[3]
p pick
p holder[pick]

# >> #<YHolder:0x1e2928 @ys=[#<Y:0x1e289c>, #<X:0x1e2874>, #<X:
0x1e284c>,
# >> #<Y:0x1e2824>, #<X:0x1e27fc>, #<Y:
0x1e27d4>,
# >> #<Y:0x1e27ac>, #<X:0x1e2784>, #<X:
0x1e275c>,
# >> #<Y:0x1e2734>]>
# >> 988178
# >> #<Y:0x1e2824>

__END__

Hope that helps.

James Edward Gray II

Note: The ids are strings. The @ys.find { |y| y.object_id == id } still
isn't working for me, i also tried y.object_id.equals(id) but I can't
seem to find the darn match : /

Please show us your code, and make it as simple as possible. Like this:

···

--------------------------------------

#!/usr/bin/ruby -w

b = "b"

b_id = b.object_id

ys = [ "a",b,"c","d" ]

puts ys.find { |i| i.object_id == b_id } # => "b"

puts ys.find { |i| i.object_id == b } # => nil

puts ys.find { |i| i.object_id == "b" } # => nil

--------------------------------------

Notice in your version of the code that "id" must equal the object id, not
the object.

--
Paul Lutus
http://www.arachnoid.com

Please show us your code, and make it as simple as possible. Like this:

class Widget

def initialize(title)
  @components = Array.new
end

def add_component(component)
  @components << component
end

def component(uniqueId) # note: uniqueId is a string
  @components.find { |comp| comp.getUniqueId == uniqueId }
end
end

···

=========================================================
class SearchWidgetComponent
:attr_reader :uniqueId

def getUniqueId
  @uniqueId
end
end

=============================
class SearchWidgetComparisonComponent

def getUniqueId
  super
end
end

in my view index.rhtml, I have:
<% @sw.component("swComparisonComp1").some_func_call_on_swcc()... %>

I get an error " NoMethodError in Region#index" "You have a nil object
when you didn't expect it!" in index.rhtml at the
.some_func_call_on_swcc() line

--
Posted via http://www.ruby-forum.com/\.

I think perhaps the problem is how I'm comparing strings. What is the
proper way to compare two strings, like:

@str1 = "boo"

def meth(str)
if( @str1 == str )
end

meth("boo")

Is that the appropriate way to compare them?

···

--
Posted via http://www.ruby-forum.com/.

Blake Miller wrote:

Please show us your code, and make it as simple as possible. Like this:

class Widget

def initialize(title)
  @components = Array.new
end

def add_component(component)
  @components << component
end

def component(uniqueId) # note: uniqueId is a string

What? "uniqueId" is string? It cannot be a string, it has to be an ID,
something gotten with ".object_id", nothing else will do. And two strings
with the same content do not necessarily have the same ID.

In your method "uniqueId", you should be returning "self.object_id".

In your code, I do not see where you acquire the ".object_id" of any object.

Very basically, in order to solve a problem like this, you simply must post
a short, terse, concise bit of code, that (1) can be run by a newsgroup
reader, and (2) shows the problem.

Posting bits and pieces of code, but never a short working example, is a
sure way to assure that this thread will go on forever.

···

--
Paul Lutus
http://www.arachnoid.com

Hi --

class Widget

def initialize(title)
@components = Array.new
end

def add_component(component)
@components << component
end

def component(uniqueId) # note: uniqueId is a string
@components.find { |comp| comp.getUniqueId == uniqueId }
end

=========================================================
class SearchWidgetComponent
:attr_reader :uniqueId

No : on attr_reader; it's a method:

   attr_reader :uniqueID

def getUniqueId
@uniqueId
end

You've now got two "get" methods for @uniqueID: the one attr_reader
created (which will be called uniqueID), and the one you've written.

end

=============================
class SearchWidgetComparisonComponent

def getUniqueId
super

super won't work here, unless this class is a subclass of
SearchWidgetComponent. And if it is a subclass, it will have that
method anyway. *And*... you don't need the method in the first place,
because of attr_reader :slight_smile:

end

Also, you need a way to set as well as get your uniqueID values,
unless they're going to be something inherent in the object (the
object's object_id). Do you want attr_writer too?

David

···

On Sat, 2 Dec 2006, Blake Miller wrote:

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Paul Lutus wrote:

Blake Miller wrote:

  @components << component
end

def component(uniqueId) # note: uniqueId is a string

What? "uniqueId" is string? It cannot be a string, it has to be an ID,
something gotten with ".object_id", nothing else will do. And two
strings
with the same content do not necessarily have the same ID.

In your method "uniqueId", you should be returning "self.object_id".

In your code, I do not see where you acquire the ".object_id" of any
object.

Very basically, in order to solve a problem like this, you simply must
post
a short, terse, concise bit of code, that (1) can be run by a newsgroup
reader, and (2) shows the problem.

Posting bits and pieces of code, but never a short working example, is a
sure way to assure that this thread will go on forever.

Why can't it be a string, I can use whatever I want to identify an
object. Now, if you're saying it's not possible to compare two strings,
then I'd see your point. I can't make the code any simpler without
sacrificing understanding of what I'm trying to accomplish. It's very
simple, each component has an id, a unique id, that I assign to it,
which is a string, and is unique (I'll enforce that later). I have an
array of these components, and I want to search that array given a
string to find the matching component by id.

···

--
Posted via http://www.ruby-forum.com/\.

unknown wrote:

Hi --

def component(uniqueId) # note: uniqueId is a string
@components.find { |comp| comp.getUniqueId == uniqueId }
end
end

=========================================================
class SearchWidgetComponent
:attr_reader :uniqueId

No : on attr_reader; it's a method:

   attr_reader :uniqueID

def getUniqueId
@uniqueId
end

You've now got two "get" methods for @uniqueID: the one attr_reader
created (which will be called uniqueID), and the one you've written.

end

=============================
class SearchWidgetComparisonComponent

def getUniqueId
super

super won't work here, unless this class is a subclass of
SearchWidgetComponent. And if it is a subclass, it will have that
method anyway. *And*... you don't need the method in the first place,
because of attr_reader :slight_smile:

end
end

Also, you need a way to set as well as get your uniqueID values,
unless they're going to be something inherent in the object (the
object's object_id). Do you want attr_writer too?

David

Noted, and changed. Sorry if I'm dragging this out, I know I left out a
couple details in the code I showed. Indeed
SearchWidgetComparisonComponent does, and has been extending
SearchWidgetComponent. My new code is like this:

class SearchWidget
def initialize
  @components = Array.new
end

def add_component(component)
   @components << component # these will always be subclass of
SearchWidgetComponent
end

def printcomps # i call this from index.rhtml, and it prints correctly
the 2 *different* component ids
   str = ""
   @components.each_with_index do |comp, index|
     str += @components[index].uniqueId
   end
   str
end

def component(uniqueId)
  @components.find { |comp| comp.uniqueId == uniqueId }
end
end

···

On Sat, 2 Dec 2006, Blake Miller wrote:

==================================
class SearchWidgetComponent
attr_accessor :uniqueId

def initialize(label, uniqueId) # see I pass a string as the id when I
init
  @label = label
  @uniqueId = uniqueId
end
end

class SearchWidgetComparisonComponent < SearchWidgetComponent
def initialize(label, uniqueId)
  super(label, uniqueId)
  @dbFields = Array.new
  @showCalendar = false;
end
end

in my index.rhtml, I have (please note I've added comments below only to
this post, they are not in the source):
<%= @sw.printcomps %> # prints "swCompareComp1", and "anoth" (my two
unique ids)

# should return a SearchWidgetComparisonComponent
<% @obj = @sw.component("swCompareComp1") %>

# call method stylize() on the object
<%= @obj.stylize("sdbfPulldown", "scPulldown", "svfClass")%>

; however, the line that calls the stylize() method returns an error
saying " NoMethodError in Region#index......You have a nil object when
you didn't expect it! The error occured while evaluating nil.stylize"

Thanks ahead for the help yo. I've been tearin my hair out for 5 hours
now.

--
Posted via http://www.ruby-forum.com/\.

Hi --

···

On Sat, 2 Dec 2006, Blake Miller wrote:

unknown wrote:

Hi --

On Sat, 2 Dec 2006, Blake Miller wrote:

def component(uniqueId) # note: uniqueId is a string
@components.find { |comp| comp.getUniqueId == uniqueId }
end

=========================================================
class SearchWidgetComponent
:attr_reader :uniqueId

No : on attr_reader; it's a method:

   attr_reader :uniqueID

def getUniqueId
@uniqueId
end

You've now got two "get" methods for @uniqueID: the one attr_reader
created (which will be called uniqueID), and the one you've written.

end

=============================
class SearchWidgetComparisonComponent

def getUniqueId
super

super won't work here, unless this class is a subclass of
SearchWidgetComponent. And if it is a subclass, it will have that
method anyway. *And*... you don't need the method in the first place,
because of attr_reader :slight_smile:

end

Also, you need a way to set as well as get your uniqueID values,
unless they're going to be something inherent in the object (the
object's object_id). Do you want attr_writer too?

David

Noted, and changed. Sorry if I'm dragging this out, I know I left out a
couple details in the code I showed. Indeed
SearchWidgetComparisonComponent does, and has been extending
SearchWidgetComponent. My new code is like this:

class SearchWidget
def initialize
@components = Array.new
end

def add_component(component)
  @components << component # these will always be subclass of
SearchWidgetComponent
end

def printcomps # i call this from index.rhtml, and it prints correctly
the 2 *different* component ids
  str = ""
  @components.each_with_index do |comp, index|
    str += @components[index].uniqueId
  end
  str
end

def component(uniqueId)
@components.find { |comp| comp.uniqueId == uniqueId }
end

==================================
class SearchWidgetComponent
attr_accessor :uniqueId

def initialize(label, uniqueId) # see I pass a string as the id when I
init
@label = label
@uniqueId = uniqueId
end

class SearchWidgetComparisonComponent < SearchWidgetComponent
def initialize(label, uniqueId)
super(label, uniqueId)
@dbFields = Array.new
@showCalendar = false;
end

in my index.rhtml, I have (please note I've added comments below only to
this post, they are not in the source):
<%= @sw.printcomps %> # prints "swCompareComp1", and "anoth" (my two
unique ids)

# should return a SearchWidgetComparisonComponent
<% @obj = @sw.component("swCompareComp1") %>

# call method stylize() on the object
<%= @obj.stylize("sdbfPulldown", "scPulldown", "svfClass")%>

; however, the line that calls the stylize() method returns an error
saying " NoMethodError in Region#index......You have a nil object when
you didn't expect it! The error occured while evaluating nil.stylize"

Thanks ahead for the help yo. I've been tearin my hair out for 5 hours
now.

I wish I could help. I can't spot anything that would cause @obj to
be nil, and when I try a standalone version of your code (essentially
what you've got minus the ERB markup), it runs fine.

Is it possible you've got symbols in one place (maybe when you create
the components) and strings in another?

David

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Blake Miller wrote:

/ ...

Posting bits and pieces of code, but never a short working example, is a
sure way to assure that this thread will go on forever.

Why can't it be a string, I can use whatever I want to identify an
object.

1. I can see why this thread goes on so long -- instead of meeting my
request, you just changed the subject.

2. It should not be a string because your goal is to compare two object IDs,
not strings. You are calling the variable "uniqueId", don't you think it
should be what it says it is? BTW use the Rubyish "unique_id" rather than
"uniqueId".

Now, if you're saying it's not possible to compare two strings,
then I'd see your point.

It is possible to compare two strings, but your goal is to compare two
object IDs. Object IDs are not strings, and strings are not object IDs.

I can't make the code any simpler without
sacrificing understanding of what I'm trying to accomplish. It's very
simple, each component has an id, a unique id, that I assign to it,
which is a string,

Don't use a string. Use the object ID provided by (object).object_id. That
way, you won't confuse everyone including yourself.

and is unique (I'll enforce that later). I have an
array of these components, and I want to search that array given a
string to find the matching component by id.

And matching by ID rather than by string is faster, along with everything
else.

···

--
Paul Lutus
http://www.arachnoid.com

I wish I could help. I can't spot anything that would cause @obj to
be nil, and when I try a standalone version of your code (essentially
what you've got minus the ERB markup), it runs fine.

Is it possible you've got symbols in one place (maybe when you create
the components) and strings in another?

David

David, thanks for the help. I did create a test.rb file and the code
worked, as you said, as it should, so there must be something else in
the code that is changing the ids. I think it's time to start
commenting the heck out of everything till I find out where it is. I'll
keep looking and post the solution when I find it (hopefully soon!).
Thanks.

···

--
Posted via http://www.ruby-forum.com/\.

unknown wrote:

Hi --

=========================================================

object's object_id). Do you want attr_writer too?

@components = Array.new
  @components.each_with_index do |comp, index|

class SearchWidgetComparisonComponent < SearchWidgetComponent
unique ids)
you didn't expect it! The error occured while evaluating nil.stylize"

Thanks ahead for the help yo. I've been tearin my hair out for 5 hours
now.

I wish I could help. I can't spot anything that would cause @obj to
be nil, and when I try a standalone version of your code (essentially
what you've got minus the ERB markup), it runs fine.

Is it possible you've got symbols in one place (maybe when you create
the components) and strings in another?

David

Ah you guys are gonna kill me now. I feel I must break out the
vaseline(sp??) and prepare to be hung.

Well, it just so happens I was passing the wrong uniqueId to the
component() function in the .rhtml file. 6 hours
later...unbelievable...I'm sure I'll be in this weekend making up the
time. The whole time I was reading "swCompareComp1" as
"swComparisonComp1". Unbelievable. Well, thanks a bunch guys, and
sorry for filling up your inboxes. Have good mosh-pitting!

···

On Sat, 2 Dec 2006, Blake Miller wrote:

--
Posted via http://www.ruby-forum.com/\.