Class: HArray

Inherits:
Hash show all
Defined in:
lib/mega/harray.rb

Overview

:title: HArray

HArray is an implemenation of the Array class using only Hashes. Regular Arrays are never used except once to delegate the #pack method, and for *args parameters (since there is no way around those is some cases). HArray is for all practical purposes 100% compatible with Array.

HArray is slower then the built in Array class, but not as slow as one might expect, since a Hash in general is faster than an Array. It might be interesting to see how this would perform if it were written in c. Not all that useful, but an interesting example.

AUTHOR(s)

  • Thamas Sawyer

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DupReplaceSnapshotMixin

#restore_snapshot, #take_snapshot

Constructor Details

#initialize(i = 0, e = nil) ⇒ HArray

Returns a new instance of HArray.



54
55
56
57
58
# File 'lib/mega/harray.rb', line 54

def initialize(i=0,e=nil)
  if i > 0
    i.times { self.set(self.length,e) }
  end
end

Class Method Details

.[](*args) ⇒ Object



42
43
44
45
46
# File 'lib/mega/harray.rb', line 42

def HArray.[](*args)
  nha = HArray.new
  args.each { |a| nha.set(nha.length,a) }
  nha
end

.new_h(hsh) ⇒ Object



48
49
50
51
52
# File 'lib/mega/harray.rb', line 48

def HArray.new_h(hsh)
  nha=HArray.new
  nha.replace(hsh)
  #nha.reindex!
end

Instance Method Details

#&(ha) ⇒ Object



60
61
62
63
64
65
66
67
68
# File 'lib/mega/harray.rb', line 60

def &(ha)
  nha=HArray.new
  (0..self.length-1).each do |i|
    if ha.has_value?(self.fetch(i)) and !nha.has_value?(self.fetch(i))
      nha.set(nha.length,self.fetch(i))
    end
  end
  nha
end

#*(j) ⇒ Object



70
71
72
73
74
75
76
77
78
# File 'lib/mega/harray.rb', line 70

def *(j)
  if j.kind_of?(String)
    return self.join(j)
  else
    nha = HArray.new
    j.times { (0...self.length).each { |i| nha.set(nha.length,self.fetch(i)) } }
    return nha
  end
end

#+(ha) ⇒ Object



80
81
82
83
84
# File 'lib/mega/harray.rb', line 80

def +(ha)
  nha = self.dup
  (0..ha.length-1).each { |i| nha.set(nha.length,ha.fetch(i)) }
  nha
end

#-(ha) ⇒ Object



86
87
88
89
90
91
# File 'lib/mega/harray.rb', line 86

def -(ha)
  nha = HArray.new
  self.each { |v| nha << v if !ha.has_value?(v) }
  #ha.each { |v| nha << i if !self.include?(v) }
  nha
end

#<<(e) ⇒ Object



93
94
95
96
# File 'lib/mega/harray.rb', line 93

def <<(e)
  self.set(self.length,e)
  self
end

#<=>(ha) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/mega/harray.rb', line 98

def <=>(ha)
  (0..self.length-1).each do |i|
    ieq = (self.fetch(i) <=> ha.fetch(i))
    return ieq if ieq != 0
  end
  self.length <=> ha.length
end

#===(ha) ⇒ Object



106
107
108
# File 'lib/mega/harray.rb', line 106

def ===(ha)
  self.==(ha)
end

#[](i, l = nil) ⇒ Object



113
114
115
116
117
118
119
120
121
122
# File 'lib/mega/harray.rb', line 113

def [](i,l=nil)
  if l
    i = i...i+l
  elsif ! i.kind_of?(Range)
    return self.at(i)
  end
  nha = HArray.new
  i.each { |j| nha.set(nha.length,get(j)) if has_key?(j) }
  nha
end

#[]=(i, b, c = nil) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/mega/harray.rb', line 125

def []=(i,b,c=nil)
  if c
    rng = (Integer(i)..Integer(i+b))
    b = c
  elsif i.kind_of? Range
    rng = i
  else
    self.set(Integer(i),b)
    return b
  end
  if b == nil
    rng.each { |i| qdelete(i) }
    self.reindex!
  elsif b.kind_of?(Array) or b.kind_of?(HArray)
    j = 0
    rng.each { |i| self[i] = b[j]; j+=1 }
  else
    rng.each { |i| qdelete(i) }
    self[rng.fist] = b
    self.reindex!
  end
end

#assoc(k) ⇒ Object



154
155
156
157
# File 'lib/mega/harray.rb', line 154

def assoc(k)
  (0...self.length).each { |i| return self.fetch(i) if self.fetch(i)[0] == k }
  return nil
end

#at(i) ⇒ Object



159
160
161
162
163
164
# File 'lib/mega/harray.rb', line 159

def at(i)
  i = self.length + i if i <= -1
  get(i)
  #return nil if i < 0 or i >= self.length
  #return self.fetch(i)
end

#collectObject

clear okay



168
169
170
171
172
# File 'lib/mega/harray.rb', line 168

def collect
  nha = HArray.new
  (0...self.length).each { |i| nha << yield(self.fetch(i)) }
  nha
end

#collect!Object Also known as: map!



174
175
176
177
178
# File 'lib/mega/harray.rb', line 174

def collect!
  nha = HArray.new
  (0...self.length).each { |i| nha << yield(self.fetch(i)) }
  self.replace(nha)
end

#compactObject



180
181
182
183
184
185
186
187
188
189
# File 'lib/mega/harray.rb', line 180

def compact
  nha, j = HArray.new, 0
  (0..self.length-1).each do |i|
    if self.fetch(i) != nil
      nha.set(j,self.fetch(i))
      j+=1
    end
  end
  nha
end

#compact!Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/mega/harray.rb', line 191

def compact!
  if self.has_value?(nil)
    nha, j = HArray.new, 0
    (0..self.length-1).each do |i|
      if self.fetch(i) != nil
        nha.set(j,self.fetch(i))
        j+=1
      end
    end
    return self.replace(nha)
  else
    return nil
  end
end

#concat(ha) ⇒ Object



206
207
208
209
# File 'lib/mega/harray.rb', line 206

def concat(ha)
  (0...ha.length).each { |i| self.set(self.length,ha.fetch(i)) }
  self
end

#count(e = nil) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
# File 'lib/mega/harray.rb', line 211

def count(e=nil)
  if block_given?
    cnt = 0
    (0...self.length).each { |i| cnt += 1 if yield(self.fetch(i)) }
    return cnt
  else
    cnt = 0
    (0...self.length).each { |i| cnt += 1 if self.fetch(i) == e }
    return cnt
  end
end

#delete(e) ⇒ Object



226
227
228
229
230
231
232
233
234
235
# File 'lib/mega/harray.rb', line 226

def delete(e)
  if has_value?(e)
    qdelete_if { |i,v| v == e }
    reindex!
    return e
  else
    return yield if block_given?
    return nil
  end
end

#delete_at(i) ⇒ Object



237
238
239
240
241
242
243
244
245
246
# File 'lib/mega/harray.rb', line 237

def delete_at(i)
  if self.has_key?(i)
    e = self.fetch(i)
    qdelete(i)
    reindex!
    return e
  else
    return nil
  end
end

#delete_ifObject



251
252
253
254
# File 'lib/mega/harray.rb', line 251

def delete_if
  qdelete_if { |i,v| yield(v) }
  reindex!
end

#eachObject



256
257
258
# File 'lib/mega/harray.rb', line 256

def each
  (0...self.length).each { |i| yield(self.fetch(i)) }
end

#each_indexObject



260
261
262
# File 'lib/mega/harray.rb', line 260

def each_index
  (0...self.length).each { |i| yield(i) }
end

#eql?(ha) ⇒ Boolean

empty? okay as is

Returns:

  • (Boolean)


266
267
268
269
270
# File 'lib/mega/harray.rb', line 266

def eql?(ha)
  return false if self.length != ha.length
  return true if (0...self.length).all? { |i| self.fetch(i).eql?(ha.fetch(i)) }
  return false
end

#fill(f, s = nil, l = nil) ⇒ Object



272
273
274
275
276
277
278
279
280
281
282
# File 'lib/mega/harray.rb', line 272

def fill(f,s=nil,l=nil)
  if s.kind_of?(Range)
    r = s
  else
    s = 0 if !s
    l = self.length - s if !l
    r = s...(s+l)
  end
  r.each{ |i| self.set(i,f) }
  self
end

#firstObject



284
285
286
287
# File 'lib/mega/harray.rb', line 284

def first
  return nil if self.empty?
  self.fetch(0)
end

#flattenObject



289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/mega/harray.rb', line 289

def flatten
  nha = HArray.new
  (0...self.length).each do |i|
    sfi = self.fetch(i)
    if sfi.kind_of?(HArray) or sfi.kind_of?(Array)
      nha.concat(sfi.flatten)
    else
      nha.set(nha.length,sfi)
    end
  end
  nha
end

#flatten!Object



302
303
304
305
# File 'lib/mega/harray.rb', line 302

def flatten!
  return nil if !self.any? { |e| e.kind_of?(HArray) or e.kind_of?(Array) }
  self.replace(self.flatten)
end

#include?(v) ⇒ Boolean

Returns:

  • (Boolean)


307
308
309
# File 'lib/mega/harray.rb', line 307

def include?(v)
  self.has_value?(v)
end

#join(sep = '') ⇒ Object

index okay



313
314
315
316
317
# File 'lib/mega/harray.rb', line 313

def join(sep='')
  s = ''
  (0...self.length).each { |i| s << "#{self.fetch(i)}#{sep}" }
  return s.chomp(sep)
end

#lastObject



319
320
321
# File 'lib/mega/harray.rb', line 319

def last
  self[self.length-1]
end

#nitemsObject



327
328
329
330
331
# File 'lib/mega/harray.rb', line 327

def nitems
  cnt = 0
  (0...self.length).each { |i| cnt += 1 if self.fetch(i) != nil }
  cnt
end

#pack(*args) ⇒ Object



333
334
335
# File 'lib/mega/harray.rb', line 333

def pack(*args)
  self.to_a.pack(*args)
end

#popObject



337
338
339
# File 'lib/mega/harray.rb', line 337

def pop
  self.delete_at(self.length-1)
end

#push(*e) ⇒ Object



341
342
343
# File 'lib/mega/harray.rb', line 341

def push(*e)
  self.concat(e)
end

#qsort(ha, l, r) ⇒ Object



440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
# File 'lib/mega/harray.rb', line 440

def qsort(ha, l, r)
  l_hold = l
  r_hold = r
  pivot = ha[l]
  while l < r
    r -= 1 while (ha[r] <=> pivot) >= 0 and l < r
    if l != r
      ha[l] = ha[r]
      l += 1
    end
    l += 1 while (ha[l] <=> pivot) <= 0 and l < r
    if l != r
      ha[r] = ha[l]
      r -= 1
    end
  end
  ha[l] = pivot
  pivot = l
  l = l_hold
  r = r_hold
  qsort(ha,l,pivot-1) if l < pivot
  qsort(ha,pivot+1,r) if r > pivot
  ha
end

#rassoc(k) ⇒ Object



345
346
347
348
# File 'lib/mega/harray.rb', line 345

def rassoc(k)
  (0...self.length).each { |i| return self.fetch(i) if self.fetch(i)[1] == k }
  return nil
end

#reindexObject



350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/mega/harray.rb', line 350

def reindex
  nha, j, k, tl = HArray.new, 0, 0, self.length
  while k < tl
    if self.has_key?(j)
      nha.set(k,self.fetch(j))
      j+=1; k+=1
    else
      j+=1
    end
  end
  nha
end

#reindex!Object



363
364
365
# File 'lib/mega/harray.rb', line 363

def reindex!
  self.replace(self.reindex)
end

#reject!Object



367
368
369
370
371
372
# File 'lib/mega/harray.rb', line 367

def reject!
  chg=nil
  qdelete_if { |i,v| r=yield(v); chg=true if r; r }
  return nil if !chg
  reindex!
end

#reverseObject

def replace(ha)

if ha.length < self.length
  (ha.length..self.length-1).each { |i| self.delete(i) }
  (0..ha.length-1).each { |i| self.set(i,ha[i]) }
end

end



381
382
383
384
385
# File 'lib/mega/harray.rb', line 381

def reverse
  nha = HArray.new
  (0...self.length).each { |i| nha.set(self.length-1-i,self.fetch(i)) }
  nha
end

#reverse!Object



387
388
389
390
391
392
393
394
395
# File 'lib/mega/harray.rb', line 387

def reverse!
  (0...self.length/2).each do |i|
    ri = self.length-1-i
    tmp = self.fetch(ri)
    self.set(ri,self.fetch(i))
    self.set(i,tmp)
  end
  self
end

#reverse_eachObject



397
398
399
400
401
402
403
# File 'lib/mega/harray.rb', line 397

def reverse_each
  i = self.length - 1
  while i >= 0
    yield(self.fetch(i))
    i -= 1
  end
end

#rindex(e) ⇒ Object



405
406
407
408
409
410
411
412
# File 'lib/mega/harray.rb', line 405

def rindex(e)
  i = self.length - 1
  while i >= 0
    return i if self.fetch(i) == e
    i -= 1
  end
  return nil
end

#setObject



124
# File 'lib/mega/harray.rb', line 124

alias set []=

#shiftObject



414
415
416
417
418
419
420
# File 'lib/mega/harray.rb', line 414

def shift
  e1 = self[0]
  tl = self.length - 1
  (1..tl).each { |i| self.set(i-1,self.fetch(i)) }
  self.delete_at(tl)
  e1
end

#slice(*args) ⇒ Object

size okay



424
425
426
# File 'lib/mega/harray.rb', line 424

def slice(*args)
  self[*args]
end

#slice!(*args) ⇒ Object



428
429
430
431
432
# File 'lib/mega/harray.rb', line 428

def slice!(*args)
  result = self[*args]
  self[*args] = nil
  result
end

#sortObject



434
435
436
437
438
# File 'lib/mega/harray.rb', line 434

def sort
  raise "HArray does not currently support sorting with blocks" if block_given?
  nha = self.dup
  qsort(nha,0,nha.length-1)
end

#sort!Object



465
466
467
468
# File 'lib/mega/harray.rb', line 465

def sort!
  raise "HArray does not currently support sorting with blocks" if block_given?
  qsort(self,0,self.length-1)
end

#to_aObject



470
471
472
473
474
# File 'lib/mega/harray.rb', line 470

def to_a
  a = []
  (0..self.length-1).each { |i| a << self.fetch(i) }
  a
end

#to_aryObject



476
477
478
# File 'lib/mega/harray.rb', line 476

def to_ary
  self
end

#to_hObject



480
481
482
483
484
# File 'lib/mega/harray.rb', line 480

def to_h
 h = Hash.new
 self.each { |k,v| h[k] = v }
 h
end

#to_sObject



486
487
488
# File 'lib/mega/harray.rb', line 486

def to_s
 self.join
end

#uniqObject



490
491
492
493
494
495
496
# File 'lib/mega/harray.rb', line 490

def uniq
  nha = HArray.new
  (0..self.length-1).each do |i|
    nha[nha.length] = self[i] if !nha.has_value?(self[i])
  end
  nha
end

#uniq!Object



498
499
500
501
502
503
504
505
506
507
# File 'lib/mega/harray.rb', line 498

def uniq!
  j = 0
  (1..self.length-1).each do |i|
    if !self[0..j].has_value?(self[i])
      self[j+1] = self[i]
      j+=1
    end
  end
  (j+1..self.length-1).each { |i| qdelete(i) }
end

#unshift(e) ⇒ Object



509
510
511
512
513
514
515
516
517
518
# File 'lib/mega/harray.rb', line 509

def unshift(e)
  i = self.length - 1
  while i >= 0
    self.set(i+1,self.fetch(i))
    return i if self.fetch(i) == e
    i -= 1
  end
  self.set(0,e)
  self
end

#values_at(*ix) ⇒ Object



520
521
522
523
524
# File 'lib/mega/harray.rb', line 520

def values_at(*ix)
  nha = HArray.new
  ix.each {|i| nha[nha.length] = self.at(i)}
  nha
end

#|(ha) ⇒ Object



148
149
150
151
152
# File 'lib/mega/harray.rb', line 148

def |(ha)
  nha = self.dup
  ha.each { |v| nha << v if !nha.has_value?(v) }
  nha
end