hashery 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,586 @@
1
+ #--
2
+ # SparseArray
3
+ #
4
+ # Copyright (c) 2004,2005 Thomas Sawyer
5
+ #
6
+ # Ruby License
7
+ #
8
+ # This module is free software. You may use, modify, and/or redistribute this
9
+ # software under the same terms as Ruby.
10
+ #
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE.
14
+ #
15
+ # ==========================================================================
16
+ # Revision History ::
17
+ # --------------------------------------------------------------------------
18
+ # 04.09 Trans * 99% Compatible with Array
19
+ # ==========================================================================
20
+ #++
21
+
22
+ # = SparseArray
23
+ #
24
+ # SparseArray is an implemenation of the Array class using only Hashes.
25
+ # Regular Arrays are never used except once to delegate the #pack method,
26
+ # (and *args parameters of course). SparseArray is almost fully compatible
27
+ # with Array. There are still a few missing methods that came in with
28
+ # Ruby 1.9 that need to be added, and negative indexes are not quite fully
29
+ # supported yet.
30
+ #
31
+ # SparseArray is slower then the built in Array class, but not as slow
32
+ # as one might expect, since a Hash is generally faster than an Array.
33
+ # It would interesting to see how this would perform if it were
34
+ # written in C.
35
+ #
36
+ class SparseArray < Hash
37
+
38
+ def self.[](*args)
39
+ nha = new
40
+ args.each { |a| nha << a } #.set(nha.length,a) }
41
+ nha
42
+ end
43
+
44
+ def self.new_h(hsh)
45
+ nha = new
46
+ nha.replace(hsh)
47
+ #nha.reindex!
48
+ end
49
+
50
+ def initialize(i=0,e=nil)
51
+ if i > 0
52
+ i.times { set(self.length,e) }
53
+ end
54
+ end
55
+
56
+ def &(ha)
57
+ nha = self.class.new
58
+ (0..self.length-1).each do |i|
59
+ if ha.has_value?(self.fetch(i)) and !nha.has_value?(self.fetch(i))
60
+ nha.set(nha.length,self.fetch(i))
61
+ end
62
+ end
63
+ nha
64
+ end
65
+
66
+ def *(j)
67
+ if j.kind_of?(String)
68
+ return self.join(j)
69
+ else
70
+ nha = self.class.new
71
+ j.times { (0...self.length).each { |i| nha.set(nha.length,self.fetch(i)) } }
72
+ return nha
73
+ end
74
+ end
75
+
76
+ def +(ha)
77
+ nha = self.dup
78
+ (0..ha.length-1).each { |i| nha.set(nha.length,ha.fetch(i)) }
79
+ nha
80
+ end
81
+
82
+ def -(ha)
83
+ nha = self.class.new
84
+ self.each { |v| nha << v if !ha.has_value?(v) }
85
+ #ha.each { |v| nha << i if !self.include?(v) }
86
+ nha
87
+ end
88
+
89
+ def <<(e)
90
+ set(length,e)
91
+ self
92
+ end
93
+
94
+ def <=>(ha)
95
+ (0..self.length-1).each do |i|
96
+ ieq = (self.fetch(i) <=> ha.fetch(i))
97
+ return ieq if ieq != 0
98
+ end
99
+ self.length <=> ha.length
100
+ end
101
+
102
+ def ===(ha)
103
+ self.==(ha)
104
+ end
105
+
106
+ alias_method :get, :[]
107
+ private :get
108
+
109
+ # TODO: Ranges with negative indexes not yet supported.
110
+ def [](i,l=nil)
111
+ if l
112
+ i = size + i if i < 0
113
+ i = i...i+l
114
+ elsif ! i.kind_of?(Range)
115
+ return self.at(i)
116
+ end
117
+ nha = self.class.new
118
+ i.each { |j| nha.set(nha.length,get(j)) if has_key?(j) }
119
+ nha
120
+ end
121
+
122
+ alias set []=
123
+ protected :set
124
+
125
+ def []=(i,b,c=nil)
126
+ if c
127
+ rng = (Integer(i)..Integer(i+b))
128
+ b = c
129
+ elsif i.kind_of? Range
130
+ rng = i
131
+ else
132
+ self.set(Integer(i),b)
133
+ return b
134
+ end
135
+ if b == nil
136
+ rng.each { |i| qdelete(i) }
137
+ self.reindex!
138
+ elsif b.kind_of?(Array) or b.kind_of?(self.class)
139
+ j = 0
140
+ rng.each { |i| self[i] = b[j]; j+=1 }
141
+ else
142
+ rng.each { |i| qdelete(i) }
143
+ self[rng.fist] = b
144
+ self.reindex!
145
+ end
146
+ end
147
+
148
+ def |(ha)
149
+ nha = self.dup
150
+ ha.each { |v| nha << v if !nha.has_value?(v) }
151
+ nha
152
+ end
153
+
154
+ def assoc(k)
155
+ (0...self.length).each { |i| return self.fetch(i) if self.fetch(i)[0] == k }
156
+ return nil
157
+ end
158
+
159
+ def at(i)
160
+ i = self.length + i if i <= -1
161
+ get(i)
162
+ #return nil if i < 0 or i >= self.length
163
+ #return self.fetch(i)
164
+ end
165
+
166
+ #def choice
167
+ #end
168
+
169
+ # clear okay
170
+
171
+ #
172
+ def collect
173
+ nha = self.class.new
174
+ (0...self.length).each { |i| nha << yield(self.fetch(i)) }
175
+ nha
176
+ end
177
+
178
+ def collect!
179
+ nha = self.class.new
180
+ (0...self.length).each { |i| nha << yield(self.fetch(i)) }
181
+ self.replace(nha)
182
+ end
183
+
184
+ #def combination
185
+ #end
186
+
187
+ #
188
+ def compact
189
+ nha, j = self.class.new, 0
190
+ (0..self.length-1).each do |i|
191
+ if self.fetch(i) != nil
192
+ nha.set(j,self.fetch(i))
193
+ j+=1
194
+ end
195
+ end
196
+ nha
197
+ end
198
+
199
+ def compact!
200
+ if self.has_value?(nil)
201
+ nha, j = self.class.new, 0
202
+ (0..self.length-1).each do |i|
203
+ if self.fetch(i) != nil
204
+ nha.set(j,self.fetch(i))
205
+ j+=1
206
+ end
207
+ end
208
+ return self.replace(nha)
209
+ else
210
+ return nil
211
+ end
212
+ end
213
+
214
+ #
215
+ def concat(ha)
216
+ (0...ha.length).each { |i| self.set(self.length,ha.fetch(i)) }
217
+ self
218
+ end
219
+
220
+ def count(e=nil)
221
+ if block_given?
222
+ cnt = 0
223
+ (0...self.length).each { |i| cnt += 1 if yield(self.fetch(i)) }
224
+ return cnt
225
+ else
226
+ cnt = 0
227
+ (0...self.length).each { |i| cnt += 1 if self.fetch(i) == e }
228
+ return cnt
229
+ end
230
+ end
231
+
232
+ #
233
+ alias qdelete delete
234
+ private :qdelete
235
+
236
+ #
237
+ def delete(e)
238
+ if has_value?(e)
239
+ qdelete_if { |i,v| v == e }
240
+ reindex!
241
+ return e
242
+ else
243
+ return yield if block_given?
244
+ return nil
245
+ end
246
+ end
247
+
248
+ #
249
+ def delete_at(i)
250
+ if self.has_key?(i)
251
+ e = self.fetch(i)
252
+ qdelete(i)
253
+ reindex!
254
+ return e
255
+ else
256
+ return nil
257
+ end
258
+ end
259
+
260
+ alias qdelete_if delete_if
261
+ private :qdelete_if
262
+
263
+ #
264
+ def delete_if
265
+ qdelete_if { |i,v| yield(v) }
266
+ reindex!
267
+ end
268
+
269
+ def each
270
+ (0...self.length).each { |i| yield(self.fetch(i)) }
271
+ end
272
+
273
+ def each_index
274
+ (0...self.length).each { |i| yield(i) }
275
+ end
276
+
277
+ # empty? okay as is
278
+
279
+ def eql?(ha)
280
+ return false if self.length != ha.length
281
+ return true if (0...self.length).all? { |i| self.fetch(i).eql?(ha.fetch(i)) }
282
+ return false
283
+ end
284
+
285
+ def fill(f,s=nil,l=nil)
286
+ if s.kind_of?(Range)
287
+ r = s
288
+ else
289
+ s = 0 if !s
290
+ l = self.length - s if !l
291
+ r = s...(s+l)
292
+ end
293
+ r.each{ |i| self.set(i,f) }
294
+ self
295
+ end
296
+
297
+ def first
298
+ return nil if self.empty?
299
+ self.fetch(0)
300
+ end
301
+
302
+ def flatten
303
+ nha = self.class.new
304
+ (0...self.length).each do |i|
305
+ sfi = self.fetch(i)
306
+ if sfi.kind_of?(self.class) or sfi.kind_of?(Array)
307
+ nha.concat(sfi.flatten)
308
+ else
309
+ nha.set(nha.length,sfi)
310
+ end
311
+ end
312
+ nha
313
+ end
314
+
315
+ def flatten!
316
+ return nil if !self.any? { |e| e.kind_of?(self.class) or e.kind_of?(Array) }
317
+ self.replace(self.flatten)
318
+ end
319
+
320
+ def include?(v)
321
+ self.has_value?(v)
322
+ end
323
+
324
+ #
325
+ def insert(index, *objs)
326
+ index = size + index + 1 if index < 0
327
+ tail = self[index...size]
328
+ objs.each_with_index do |obj, i|
329
+ set(index + i, obj)
330
+ end
331
+ tail.each_with_index do |obj, i|
332
+ set(objs.size + index + i, obj)
333
+ end
334
+ self
335
+ end
336
+
337
+ # index okay
338
+
339
+ #
340
+ def join(sep='')
341
+ s = ''
342
+ (0...self.length).each { |i| s << "#{self.fetch(i)}#{sep}" }
343
+ return s.chomp(sep)
344
+ end
345
+
346
+ #
347
+ def last
348
+ self[self.length-1]
349
+ end
350
+
351
+ # length okay
352
+
353
+ #
354
+ alias map! collect!
355
+
356
+ #
357
+ def nitems
358
+ cnt = 0
359
+ (0...self.length).each { |i| cnt += 1 if self.fetch(i) != nil }
360
+ cnt
361
+ end
362
+
363
+ def pack(*args)
364
+ self.to_a.pack(*args)
365
+ end
366
+
367
+ #def permutation
368
+ #end
369
+
370
+ #
371
+ def pop
372
+ self.delete_at(self.length-1)
373
+ end
374
+
375
+ #def product
376
+ #end
377
+
378
+ #
379
+ def push(*e)
380
+ self.concat(e)
381
+ end
382
+
383
+ def rassoc(k)
384
+ (0...self.length).each { |i| return self.fetch(i) if self.fetch(i)[1] == k }
385
+ return nil
386
+ end
387
+
388
+ def reindex
389
+ nha, j, k, tl = self.class.new, 0, 0, self.length
390
+ while k < tl
391
+ if self.has_key?(j)
392
+ nha.set(k,self.fetch(j))
393
+ j+=1; k+=1
394
+ else
395
+ j+=1
396
+ end
397
+ end
398
+ nha
399
+ end
400
+
401
+ def reindex!
402
+ self.replace(self.reindex)
403
+ end
404
+
405
+ def reject!
406
+ chg=nil
407
+ qdelete_if { |i,v| r=yield(v); chg=true if r; r }
408
+ return nil if !chg
409
+ reindex!
410
+ end
411
+
412
+ #def replace(ha)
413
+ # if ha.length < self.length
414
+ # (ha.length..self.length-1).each { |i| self.delete(i) }
415
+ # (0..ha.length-1).each { |i| self.set(i,ha[i]) }
416
+ # end
417
+ #end
418
+
419
+ def reverse
420
+ nha = self.class.new
421
+ (0...self.length).each { |i| nha.set(self.length-1-i,self.fetch(i)) }
422
+ nha
423
+ end
424
+
425
+ def reverse!
426
+ (0...self.length/2).each do |i|
427
+ ri = self.length-1-i
428
+ tmp = self.fetch(ri)
429
+ self.set(ri,self.fetch(i))
430
+ self.set(i,tmp)
431
+ end
432
+ self
433
+ end
434
+
435
+ def reverse_each
436
+ i = self.length - 1
437
+ while i >= 0
438
+ yield(self.fetch(i))
439
+ i -= 1
440
+ end
441
+ end
442
+
443
+ def rindex(e)
444
+ i = self.length - 1
445
+ while i >= 0
446
+ return i if self.fetch(i) == e
447
+ i -= 1
448
+ end
449
+ return nil
450
+ end
451
+
452
+ def shift
453
+ e1 = self[0]
454
+ tl = self.length - 1
455
+ (1..tl).each { |i| self.set(i-1,self.fetch(i)) }
456
+ self.delete_at(tl)
457
+ e1
458
+ end
459
+
460
+ #
461
+ def shuffle
462
+ dup.shuffle!
463
+ end
464
+
465
+ #
466
+ def shuffle!
467
+ size.times do
468
+ a = rand(size).to_i
469
+ b = rand(size).to_i
470
+ self[a], self[b] = self[b], self[a]
471
+ end
472
+ end
473
+
474
+ # size okay
475
+
476
+ #
477
+ def slice(*args)
478
+ self[*args]
479
+ end
480
+
481
+ def slice!(*args)
482
+ result = self[*args]
483
+ self[*args] = nil
484
+ result
485
+ end
486
+
487
+ def sort
488
+ raise "SparseArray does not currently support sorting with blocks" if block_given?
489
+ nha = self.dup
490
+ qsort(nha,0,nha.length-1)
491
+ end
492
+
493
+ def qsort(ha, l, r)
494
+ l_hold = l
495
+ r_hold = r
496
+ pivot = ha[l]
497
+ while l < r
498
+ r -= 1 while (ha[r] <=> pivot) >= 0 and l < r
499
+ if l != r
500
+ ha[l] = ha[r]
501
+ l += 1
502
+ end
503
+ l += 1 while (ha[l] <=> pivot) <= 0 and l < r
504
+ if l != r
505
+ ha[r] = ha[l]
506
+ r -= 1
507
+ end
508
+ end
509
+ ha[l] = pivot
510
+ pivot = l
511
+ l = l_hold
512
+ r = r_hold
513
+ qsort(ha,l,pivot-1) if l < pivot
514
+ qsort(ha,pivot+1,r) if r > pivot
515
+ ha
516
+ end
517
+
518
+ def sort!
519
+ raise "SparseArray does not currently support sorting with blocks" if block_given?
520
+ qsort(self,0,self.length-1)
521
+ end
522
+
523
+ def to_a
524
+ a = []
525
+ (0..self.length-1).each { |i| a << self.fetch(i) }
526
+ a
527
+ end
528
+
529
+ def to_ary
530
+ self
531
+ end
532
+
533
+ def to_h
534
+ h = Hash.new
535
+ self.each { |k,v| h[k] = v }
536
+ h
537
+ end
538
+
539
+ def to_s
540
+ self.join
541
+ end
542
+
543
+ #
544
+ #def transpose
545
+ #end
546
+
547
+ #
548
+ def uniq
549
+ nha = self.class.new
550
+ (0..self.length-1).each do |i|
551
+ nha[nha.length] = self[i] if !nha.has_value?(self[i])
552
+ end
553
+ nha
554
+ end
555
+
556
+ #
557
+ def uniq!
558
+ j = 0
559
+ (1..self.length-1).each do |i|
560
+ if !self[0..j].has_value?(self[i])
561
+ self[j+1] = self[i]
562
+ j+=1
563
+ end
564
+ end
565
+ (j+1..self.length-1).each { |i| qdelete(i) }
566
+ end
567
+
568
+ def unshift(e)
569
+ i = self.length - 1
570
+ while i >= 0
571
+ self.set(i+1,self.fetch(i))
572
+ return i if self.fetch(i) == e
573
+ i -= 1
574
+ end
575
+ self.set(0,e)
576
+ self
577
+ end
578
+
579
+ def values_at(*ix)
580
+ nha = self.class.new
581
+ ix.each {|i| nha[nha.length] = self.at(i)}
582
+ nha
583
+ end
584
+
585
+ end
586
+