Class: HArray

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

Overview

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

Constructor Details

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

Returns a new instance of HArray.



35
36
37
38
39
# File 'lib/carat/harray.rb', line 35

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

Class Method Details

.[](*args) ⇒ Object



23
24
25
26
27
# File 'lib/carat/harray.rb', line 23

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

.new_h(hsh) ⇒ Object



29
30
31
32
33
# File 'lib/carat/harray.rb', line 29

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

Instance Method Details

#&(ha) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/carat/harray.rb', line 41

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



51
52
53
54
55
56
57
58
59
# File 'lib/carat/harray.rb', line 51

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



61
62
63
64
65
# File 'lib/carat/harray.rb', line 61

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

#-(ha) ⇒ Object



67
68
69
70
71
72
# File 'lib/carat/harray.rb', line 67

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



74
75
76
77
# File 'lib/carat/harray.rb', line 74

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

#<=>(ha) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/carat/harray.rb', line 79

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



87
88
89
# File 'lib/carat/harray.rb', line 87

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

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



94
95
96
97
98
99
100
101
102
103
# File 'lib/carat/harray.rb', line 94

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



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/carat/harray.rb', line 106

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



135
136
137
138
# File 'lib/carat/harray.rb', line 135

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

#at(i) ⇒ Object



140
141
142
143
144
145
# File 'lib/carat/harray.rb', line 140

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



149
150
151
152
153
# File 'lib/carat/harray.rb', line 149

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

#collect!Object Also known as: map!



155
156
157
158
159
# File 'lib/carat/harray.rb', line 155

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

#compactObject



161
162
163
164
165
166
167
168
169
170
# File 'lib/carat/harray.rb', line 161

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



172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/carat/harray.rb', line 172

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



187
188
189
190
# File 'lib/carat/harray.rb', line 187

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

#count(e = nil) ⇒ Object



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

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



207
208
209
210
211
212
213
214
215
216
# File 'lib/carat/harray.rb', line 207

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



218
219
220
221
222
223
224
225
226
227
# File 'lib/carat/harray.rb', line 218

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



232
233
234
235
# File 'lib/carat/harray.rb', line 232

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

#eachObject



237
238
239
# File 'lib/carat/harray.rb', line 237

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

#each_indexObject



241
242
243
# File 'lib/carat/harray.rb', line 241

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

#eql?(ha) ⇒ Boolean

empty? okay as is

Returns:

  • (Boolean)


247
248
249
250
251
# File 'lib/carat/harray.rb', line 247

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



253
254
255
256
257
258
259
260
261
262
263
# File 'lib/carat/harray.rb', line 253

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



265
266
267
268
# File 'lib/carat/harray.rb', line 265

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

#flattenObject



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

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



283
284
285
286
# File 'lib/carat/harray.rb', line 283

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)


288
289
290
# File 'lib/carat/harray.rb', line 288

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

#join(sep = '') ⇒ Object

index okay



294
295
296
297
298
# File 'lib/carat/harray.rb', line 294

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

#lastObject



300
301
302
# File 'lib/carat/harray.rb', line 300

def last
  self[self.length-1]
end

#nitemsObject



308
309
310
311
312
# File 'lib/carat/harray.rb', line 308

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

#pack(*args) ⇒ Object



314
315
316
# File 'lib/carat/harray.rb', line 314

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

#popObject



318
319
320
# File 'lib/carat/harray.rb', line 318

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

#push(*e) ⇒ Object



322
323
324
# File 'lib/carat/harray.rb', line 322

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

#qsort(ha, l, r) ⇒ Object



421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/carat/harray.rb', line 421

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



326
327
328
329
# File 'lib/carat/harray.rb', line 326

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

#reindexObject



331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/carat/harray.rb', line 331

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



344
345
346
# File 'lib/carat/harray.rb', line 344

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

#reject!Object



348
349
350
351
352
353
# File 'lib/carat/harray.rb', line 348

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



362
363
364
365
366
# File 'lib/carat/harray.rb', line 362

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

#reverse!Object



368
369
370
371
372
373
374
375
376
# File 'lib/carat/harray.rb', line 368

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



378
379
380
381
382
383
384
# File 'lib/carat/harray.rb', line 378

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

#rindex(e) ⇒ Object



386
387
388
389
390
391
392
393
# File 'lib/carat/harray.rb', line 386

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

#setObject



105
# File 'lib/carat/harray.rb', line 105

alias set []=

#shiftObject



395
396
397
398
399
400
401
# File 'lib/carat/harray.rb', line 395

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



405
406
407
# File 'lib/carat/harray.rb', line 405

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

#slice!(*args) ⇒ Object



409
410
411
412
413
# File 'lib/carat/harray.rb', line 409

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

#sortObject



415
416
417
418
419
# File 'lib/carat/harray.rb', line 415

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



446
447
448
449
# File 'lib/carat/harray.rb', line 446

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

#to_aObject



451
452
453
454
455
# File 'lib/carat/harray.rb', line 451

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

#to_aryObject



457
458
459
# File 'lib/carat/harray.rb', line 457

def to_ary
  self
end

#to_hObject



461
462
463
464
465
# File 'lib/carat/harray.rb', line 461

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

#to_sObject



467
468
469
# File 'lib/carat/harray.rb', line 467

def to_s
 self.join
end

#uniqObject



471
472
473
474
475
476
477
# File 'lib/carat/harray.rb', line 471

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



479
480
481
482
483
484
485
486
487
488
# File 'lib/carat/harray.rb', line 479

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



490
491
492
493
494
495
496
497
498
499
# File 'lib/carat/harray.rb', line 490

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



501
502
503
504
505
# File 'lib/carat/harray.rb', line 501

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

#|(ha) ⇒ Object



129
130
131
132
133
# File 'lib/carat/harray.rb', line 129

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