简体   繁体   English

在Ruby中修改调用对象

[英]Modify Calling Object in Ruby

I am in the process of learning Ruby and as practice I am making a linked list class. 我正在学习Ruby,实际上,我正在制作一个链表类。 I am in the process of writing the delete method for a doubly linked list. 我正在为双向链表编写delete方法。 My question is, if I represent the list by its head node, how do I delete the head? 我的问题是,如果我按列表的头节点表示列表,该如何删除头? It seems like Ruby wont allow you to assign to the self variable, so I can't change the reference of the caller to be the next node. 似乎Ruby不允许您分配给self变量,因此我无法将调用方的引用更改为下一个节点。 One solution is that I can copy the key from the next node and swap references, but in general, is there a way in Ruby to change the reference of the caller? 一种解决方案是,我可以从下一个节点复制密钥并交换引用,但是总的来说,Ruby中是否可以更改调用者的引用?

class LinkedListNode

    attr_accessor :next, :previous, :key

    def initialize(key=nil, next_node=nil, previous=nil)
        @next = next_node
        @previous = previous
        @key = key
    end

    def append(key=nil)
        newnode = LinkedListNode.new(key)
        seeker = self
        while seeker.next != nil
           seeker = seeker.next
        end
        newnode.previous = seeker
        seeker.next = newnode
     end

     def delete(key=nil)
         seeker = self
         while seeker.key != key
             return if seeker.next == nil
             seeker = seeker.next
         end
         if seeker.previous != nil
            if seeker.next != nil
                seeker.previous.next = seeker.next
                seeker.next.previous = seeker.previous
            else
                seeker.previous.next = nil
            end
         else
             return self = self.next
         end
         return seeker = nil
     end

     def print
         seeker = self
         string = ""
         while 1
            if seeker.next == nil
                string += seeker.key.to_s
                break
            else
                string += seeker.key.to_s + " -> "
            end
            seeker = seeker.next
        end
        puts string
    end
end

if __FILE__ == $0
    ll = LinkedListNode.new(1)
    ll.append(2)
    ll.append(3)
    ll.append(4)
    ll.append(5)

    ll.print

    ll.delete(5)
    ll.print

    ll.delete(1)
    ll.print
end

You can't change the which object is being pointed to by the caller (ie modify self ), but you can manipulate the object in any way you want, as you've already thought through. 您无法更改调用者指向的对象(即,修改self ),但是您已经可以考虑使用任何想要的方法来对其进行操作。 The short answer is that it can't be done. 简短的答案是无法完成。 You can come up with other ways to model it, but I think you're already on the right track. 您可以提出其他建模方法,但我认为您已经走上了正确的道路。

You need to conceptualize a linked list differently. 您需要以不同的方式概念化链接列表。 A LinkedListNode is a component of a LinkedList, not a LinkedList itself. LinkedListNode是LinkedList的组件,而不是LinkedList本身。 Operations such as append, delete, and print should go in your LinkedList class, not your LinkedListNode class. 诸如添加,删除和打印之类的操作应放在LinkedList类中,而不是LinkedListNode类中。 Try starting with something like 尝试从类似的东西开始

class LinkedList

  # This one-liner defines a LinkedList::Node with associated constructor
  # and accessors for the three tags provided.  Any tags omitted during
  # construction will be initialized to nil.
  Node = Struct.new(:key, :previous, :next)

  attr_reader :head, :tail

  def initialize
    # start with no Nodes in the list
    @head = @tail = nil
  end

  def append(key)
    # Make the LinkedList tail a new node that stores the key,
    # points to the prior tail as its previous reference, and
    # has no next.
    @tail = Node.new(key, @tail)
    if @tail.previous  # the prior tail was not nil
      @tail.previous.next = @tail   # make the prior tail point to the new one
    else               # if there wasn't any tail before the list was empty
      @head = @tail    # so the new tail Node is also the head
    end
  end

  # ...

end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM