Class: Linked::List

Inherits:
Object
  • Object
show all
Includes:
ListEnumerable
Defined in:
lib/linked/list.rb

Overview

This class provides a way extend the regular chain of listable items with the concept of an empty chain.

Lists are ment to behave more like arrays, and respond to many of the same methods.

Instance Method Summary collapse

Methods included from ListEnumerable

#count, #each_item, #first, #last, #reverse_each_item

Constructor Details

#initializeList

Initializes the list.



14
15
16
17
# File 'lib/linked/list.rb', line 14

def initialize
  reset_list
  super
end

Instance Method Details

#==(other) ⇒ true, false Also known as: eql?

Two lists are considered equal if the n:th item from each list are equal.

Parameters:

  • other (Object)

    the object to compare with.

Returns:

  • (true)

    if the given object is a list and the items are equal.

  • (false)

    otherwise.



47
48
49
50
51
52
53
# File 'lib/linked/list.rb', line 47

def ==(other)
  return false unless other.is_a? self.class
  return false unless other.count == count

  other_items = other.each_item
  each_item.all? { |item| item == other_items.next }
end

#empty?true, false

Returns:

  • (true)

    if the list does not contain any items.

  • (false)

    otherwise.



59
60
61
# File 'lib/linked/list.rb', line 59

def empty?
  nil.eql? @_chain
end

#freezeself

Calls #freeze on all items in the list, as well as the head and the tail (eol).

Returns:

  • (self)


141
142
143
144
# File 'lib/linked/list.rb', line 141

def freeze
  each_item(&:freeze)
  super
end

#include?(item) ⇒ true, false

Check if an item is in the list.

Parameters:

  • item (Object)

    any object that may be in the list.

Returns:

  • (true)

    if the given item is in the list.

  • (false)

    otherwise.



131
132
133
134
135
# File 'lib/linked/list.rb', line 131

def include?(item)
  return false if empty?
  # TODO: This works fine, but looks wrong.
  @_chain.in_chain? item
end

#initialize_dup(source) ⇒ Object

When copying a list its entire item chain needs to be copied as well. Therefore #dup will be called on each of the original lists items, making this operation quite expensive.

Parameters:

  • source (List)

    the list to copy.



24
25
26
27
28
29
# File 'lib/linked/list.rb', line 24

def initialize_dup(source)
  reset_list
  source.each_item { |item| push item.dup }

  super
end

#inspect_list(&block) ⇒ Object Also known as: inspect

Overrides the default inspect method to provide a more useful view of the list.

Importantly this implementation supports nested lists and will return a tree like structure.



152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/linked/list.rb', line 152

def inspect_list(&block)
  res = [block_given? ? yield(self) : object_identifier]

  each_item do |item|
    lines = item.inspect(&block).split "\n"

    res.push((item.last? ? '└─╴' : '├─╴') + lines.shift)
    padding = item.last? ? '   ' : '│  '
    lines.each { |line| res.push padding + line }
  end

  res.join("\n")
end

#itemListable

Access the first item in the list. If the list is empty a NoMethodError will be raised. This mirrors the behaviour of Item#item and allows other methods that work on List objects to easily and interchangeably accept both lists and items as arguments.

Returns:

  • (Listable)

    the first item in the list.

Raises:

  • (NoMethodError)


37
38
39
40
# File 'lib/linked/list.rb', line 37

def item
  raise NoMethodError if empty?
  @_chain
end

#popListable?

Pop the last item off the list.

Returns:

  • (Listable, nil)

    the last item in the list, or nil if the list is empty.



89
90
91
92
93
# File 'lib/linked/list.rb', line 89

def pop
  return nil if empty?

  list_tail.first? ? last.tap { @_chain = nil } : list_tail.delete
end

#push(object) ⇒ self Also known as: <<

Insert an item at the end of the list. If the given object is not an object responding to #item it will be treated as a value. The value will be wraped in a new Item create by #create_item.

See Item#append for more details.

Parameters:

  • object (#item, Object)

    the item to insert, or an arbitrary object.

Returns:

  • (self)


71
72
73
74
75
76
77
78
79
80
81
# File 'lib/linked/list.rb', line 71

def push(object)
  item = coerce_item object

  if empty?
    @_chain = item
  else
    list_tail.append item
  end

  self
end

#shiftListable?

Shift the first item off the list.

Returns:

  • (Listable, nil)

    the first item in the list, or nil if the list is empty.



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/linked/list.rb', line 114

def shift
  return nil if empty?

  if list_head.last?
    @_chain.tap { @_chain = nil }
  else
    old_head = list_head
    @_chain = list_head.next
    old_head.delete
  end
end

#unshift(object) ⇒ self

Insert an item at the beginning of the list. If the given object is not an object responding to #item it will be treated as a value. The value will be wraped in a new Item create by #create_item.

See Item#prepend for more details.

Parameters:

  • object (#item, Object)

    the item to insert, or an arbitrary object.

Returns:

  • (self)


103
104
105
106
107
108
# File 'lib/linked/list.rb', line 103

def unshift(object)
  item = coerce_item object
  @_chain = empty? ? item.chain : @_chain.prepend(item)

  self
end