hashery 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+