1

I may be making a major design error, but this is my first time working with Structs in Ruby.

As detailed in this question, I have three objects, Vertex, Edge, and Graph. Vertex has simple attributes (scalars), but Edge can have :endpoints which is a pair of Vertexes in an Array. Specifically, Edge has a scalar :weight and a Array of Vertexes :endpoints. Lastly, Graph stores :vertexes and :edges, which are Arrays of Vertexes and Edges.

Edge = Struct.new(:weight, :endpoints)

Since Graph is a Struct containing Structs, I created a method to get the scalar weights from the Graph:

Graph = Struct.new(:vertexes, :edges) do
  def get_weights()
    w = []
    self.edges.each do |ed| w << ed.weight end
  end

#truncated
end

However, if I run this, I get Edges, not scalar Integers:

[226] pry(main)> t_weights = [4,8,8,11,7,4,2,9,14,10,2,1,6,7]
=> [4, 8, 8, 11, 7, 4, 2, 9, 14, 10, 2, 1, 6, 7]

[227] pry(main)> t_edges.each_with_index.map do |ed,ind|
[227] pry(main)*   ed.weight = t_weights[ind]  
[227] pry(main)*   ed.endpoints = endpoints[ind]  
[227] pry(main)*   # p ed.weight  
[227] pry(main)* end  
t_grap = Graph.new(t_verts, t_edges)

=> #<struct Graph
 vertexes=
  [#<struct Vertex parent=nil, rank=nil, id=0.31572617312378737>,
   #<struct Vertex parent=nil, rank=nil, id=0.24063512558288636>,
   #<struct Vertex parent=nil, rank=nil, id=0.34820800389791284>,
   #<struct Vertex parent=nil, rank=nil, id=0.86247407897408>,
   #<struct Vertex parent=nil, rank=nil, id=0.4503814825928186>,
   #<struct Vertex parent=nil, rank=nil, id=0.4020451841058619>,
   #<struct Vertex parent=nil, rank=nil, id=0.09096934472128582>,
   #<struct Vertex parent=nil, rank=nil, id=0.9942198795853134>,
   #<struct Vertex parent=nil, rank=nil, id=0.4393226273344629>], <truncated>
 edges=
  [#<struct Edge
    weight=4,
    endpoints=
     [#<struct Vertex
       parent=#<struct Vertex:...>,
       rank=0, <truncated>

[230] pry(main)> t_grap.get_weights
=> [#<struct Edge
  weight=4,
  endpoints=
   [#<struct Vertex
     parent=#<struct Vertex:...>,
     rank=0,
     id=0.6540666040368713>,
    #<struct Vertex
     parent=#<struct Vertex:...>,
     rank=0,
     id=0.7511069577638254>]>,
 #<struct Edge
  weight=8,
  endpoints=
   [#<struct Vertex
     parent=#<struct Vertex:...>,
     rank=0,
     id=0.6540666040368713>,<truncated>

I tried adding attr_accessor :weights to Edge, but then the code snippet above which sets the initial values fails silently, leaving each Edge.weight equal to nil.

What am I doing wrong?

Community
  • 1
  • 1
bright-star
  • 6,016
  • 6
  • 42
  • 81

1 Answers1

1

Not sure why you need vertices in the call to Graph.new

The edges should already contain them in the endpoints.

Vertex = Struct.new(:x, :y)
Edge = Struct.new(:weight, :endpoints)

Graph = Struct.new(:edges) do
  def get_weights
    edges.map(&:weight)
  end
end

e1 = Edge.new 66, [Vertex.new(1,2), Vertex.new(2,1)]
e2 = Edge.new 26, [Vertex.new(1,1), Vertex.new(2,1)]
g = Graph.new([e1,e2])
g.get_weights
=> [66, 26] 

Edit:

g.edges.each { |edge| p edge.weight }
66
26
...

works. You might be building something different. The code above creates a Graph object that contains an array of Edge objects called edges.

ed_ary.map[&:weight]

won't work. As in my comment g.edges.map(&:weight) is just a shortcut. See this discussion: What does to_proc method mean?


Community
  • 1
  • 1
seph
  • 6,066
  • 3
  • 21
  • 19
  • Definitely works, but I'm having trouble understanding the amp operator. If I just have an Array of Edges outside of the Graph, why doesn't either `ed_ary.each do |ed| p ed.weight end` or `ed_ary.map[&:weight]` return with the stored weights? – bright-star Dec 14 '13 at 20:16
  • 1
    Sorry, I should have kept things familiar. It's the same as `edges.map { |edge| edge.weight }` – seph Dec 14 '13 at 23:01