sarah 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.txt +11 -0
- data/lib/sarah.rb +82 -46
- data/sarah.gemspec +2 -2
- data/test/15v210.rb +47 -0
- metadata +5 -3
data/HISTORY.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
2014-04-10 Version 2.1.0
|
2
|
+
|
3
|
+
Added :nsq (non-sequential = sparse + random) selector for
|
4
|
+
#length/#size, #keys, #values, #to_a, and #to_h.
|
5
|
+
|
6
|
+
Fixed some deprecated methods to have pre-2.0.0 behavior after
|
7
|
+
2.0.0 changes (i.e. :nsq versus :rnd differences).
|
8
|
+
|
9
|
+
Added #reindex method to reindex sparse values (like #compact!
|
10
|
+
but without nil removal).
|
11
|
+
|
1
12
|
2014-04-01 Version 2.0.1
|
2
13
|
|
3
14
|
Fixed incorrect indexes in "Background" section of comments.
|
data/lib/sarah.rb
CHANGED
@@ -42,27 +42,29 @@
|
|
42
42
|
#
|
43
43
|
# As of version 2.0.0, there are three major data structures internally:
|
44
44
|
# * "seq" - an array of sequentially-indexed values beginning at index 0
|
45
|
-
# (except when negative actual keys are present; see {#negative_mode
|
45
|
+
# (except when negative actual keys are present; see {#negative_mode}
|
46
46
|
# :actual)
|
47
47
|
# * "spr" - a hash representing a sparse array of all other
|
48
48
|
# numerically-indexed values
|
49
49
|
# * "rnd" - a "random access" hash of all non-numerically keyed values
|
50
50
|
#
|
51
51
|
# The sequential and sparse parts are collectively referred to as "ary".
|
52
|
-
#
|
52
|
+
# In some contexts, the non-sequential (sparse and random) parts are
|
53
|
+
# available as "nsq". All three parts together are collectively referred
|
54
|
+
# to as "all".
|
53
55
|
#
|
54
56
|
# Some methods allow you to direct their action to all or specific parts
|
55
57
|
# of the structure by specifying a corrsponding symbol, :seq, :spr, :ary,
|
56
|
-
# :rnd, or :all.
|
58
|
+
# :nsq, :rnd, or :all.
|
57
59
|
#
|
58
60
|
# @author Brian Katzung (briank@kappacs.com), Kappa Computer Solutions, LLC
|
59
61
|
# @copyright 2013-2014 Brian Katzung and Kappa Computer Solutions, LLC
|
60
62
|
# @license MIT License
|
61
|
-
# @version 2.
|
63
|
+
# @version 2.1.0
|
62
64
|
|
63
65
|
class Sarah
|
64
66
|
|
65
|
-
VERSION = "2.
|
67
|
+
VERSION = "2.1.0"
|
66
68
|
|
67
69
|
# Private attributes:
|
68
70
|
# seq [Array] An array of (zero-origin) sequential values.
|
@@ -87,8 +89,15 @@ class Sarah
|
|
87
89
|
|
88
90
|
# @!attribute [r] negative_mode
|
89
91
|
# @return [:actual|:error|:ignore]
|
90
|
-
# How negative indexes/keys are handled.
|
91
|
-
#
|
92
|
+
# How negative indexes/keys are handled.
|
93
|
+
#
|
94
|
+
# :actual - Negative keys represent themselves and are not treated
|
95
|
+
# specially (although delete works like unset in this mode--values
|
96
|
+
# are not reindexed)
|
97
|
+
# :error (default) - Negative keys are interpreted relative to the
|
98
|
+
# end of the array; keys < -@ary_next raise an IndexError
|
99
|
+
# :ignore - Like :error, but keys < -@ary_next are treated as
|
100
|
+
# non-existent on fetch and silently ignored on set
|
92
101
|
attr_reader :negative_mode
|
93
102
|
|
94
103
|
# ##### Class Methods #####
|
@@ -409,6 +418,8 @@ class Sarah
|
|
409
418
|
# Remove nil values in place. In the case of the sequential and sparse
|
410
419
|
# arrays, the remaining values are reindexed sequentially from 0.
|
411
420
|
#
|
421
|
+
# See also {#reindex}.
|
422
|
+
#
|
412
423
|
# @param which [:all|:ary|:rnd] Which data structures are compacted.
|
413
424
|
# @return [Sarah]
|
414
425
|
def compact! (which = :all)
|
@@ -480,7 +491,7 @@ class Sarah
|
|
480
491
|
|
481
492
|
# Deletes each value for which the required block returns true.
|
482
493
|
#
|
483
|
-
# Subsequent values are re-indexed except when {#negative_mode
|
494
|
+
# Subsequent values are re-indexed except when {#negative_mode}
|
484
495
|
# :actual. See also {#unset_if}.
|
485
496
|
#
|
486
497
|
# The block is passed the current value and nil for the sequential
|
@@ -517,8 +528,8 @@ class Sarah
|
|
517
528
|
|
518
529
|
# Delete by value.
|
519
530
|
#
|
520
|
-
# Subsequent values are re-indexed except when {#negative_mode
|
521
|
-
# See also {#unset_value}.
|
531
|
+
# Subsequent values are re-indexed except when {#negative_mode} is
|
532
|
+
# :actual. See also {#unset_value}.
|
522
533
|
#
|
523
534
|
# @param what [Object] The value to be deleted
|
524
535
|
# @param which [:all|:ary|:rnd] The data structures in which to delete.
|
@@ -751,25 +762,30 @@ class Sarah
|
|
751
762
|
|
752
763
|
# Return the random-access hash keys.
|
753
764
|
#
|
765
|
+
# Since 2.0.0 returns only the random-access keys. Since 2.1.0
|
766
|
+
# returns the non-sequential (sparse + random) keys like the
|
767
|
+
# pre-2.0.0 version.
|
768
|
+
#
|
754
769
|
# @return [Array]
|
755
|
-
# @deprecated Please use {#keys} instead.
|
756
|
-
def rnd_keys;
|
770
|
+
# @deprecated Please use {#keys} :nsq or #keys :rnd instead.
|
771
|
+
def rnd_keys; self.keys :nsq; end
|
757
772
|
|
758
773
|
# Return the sequential array keys (indexes).
|
759
774
|
#
|
760
775
|
# @return [Array<Integer>]
|
761
|
-
# @deprecated Please use {#keys} instead.
|
762
|
-
def seq_keys;
|
776
|
+
# @deprecated Please use {#keys} :seq instead.
|
777
|
+
def seq_keys; self.keys :seq; end
|
763
778
|
|
764
779
|
# Return an array of indexes and keys.
|
765
780
|
#
|
766
|
-
# @param which [:all|:ary|:rnd|:seq|:spr] Which indexes and keys
|
767
|
-
# to return. (Since 2.0.0)
|
781
|
+
# @param which [:all|:ary|:nsq|:rnd|:seq|:spr] Which indexes and keys
|
782
|
+
# to return. (Since 2.0.0; :nsq since 2.1.0)
|
768
783
|
# @return [Array]
|
769
784
|
def keys (which = :all)
|
770
785
|
case which
|
771
786
|
when :all then keys(:seq) + keys(:spr) + @rnd.keys
|
772
787
|
when :ary then keys(:seq) + keys(:spr)
|
788
|
+
when :nsq then keys(:spr) + @rnd.keys
|
773
789
|
when :rnd then @rnd.keys
|
774
790
|
when :seq then (0...@seq.size).to_a
|
775
791
|
when :spr then @spr.keys.sort
|
@@ -787,15 +803,18 @@ class Sarah
|
|
787
803
|
|
788
804
|
# Return the random-access hash size.
|
789
805
|
#
|
790
|
-
#
|
806
|
+
# Since 2.1.0, this returns the non-sequential (sparse + random)
|
807
|
+
# hash size, which is more closely reflects the pre-2.0.0 value.
|
808
|
+
#
|
809
|
+
# @deprecated Please use {#size} :rnd or #size :nsq instead.
|
791
810
|
# @return [Integer]
|
792
|
-
def rnd_length;
|
811
|
+
def rnd_length; self.size :nsq; end
|
793
812
|
|
794
813
|
alias_method :rnd_size, :rnd_length
|
795
814
|
|
796
815
|
# Return the sequential array size.
|
797
816
|
#
|
798
|
-
# @deprecated Please use {#size} instead.
|
817
|
+
# @deprecated Please use {#size} :seq instead.
|
799
818
|
# @return [Integer]
|
800
819
|
def seq_length; @seq.size; end
|
801
820
|
|
@@ -803,14 +822,15 @@ class Sarah
|
|
803
822
|
|
804
823
|
# Return the number of stored values (AKA size or length).
|
805
824
|
#
|
806
|
-
# @param which [:all|:ary|:rnd|:seq|:spr] The data structures
|
807
|
-
# for which the (combined) size is to be returned. (Since 2.0.0
|
825
|
+
# @param which [:all|:ary|:nsq|:rnd|:seq|:spr] The data structures
|
826
|
+
# for which the (combined) size is to be returned. (Since 2.0.0;
|
827
|
+
# :nsq since 2.1.0)
|
808
828
|
# @return [Integer]
|
809
829
|
def length (which = :all)
|
810
830
|
size = 0
|
811
831
|
case which when :all, :ary, :seq then size += @seq.size end
|
812
|
-
case which when :all, :ary, :spr then size += @spr.size end
|
813
|
-
case which when :all, :rnd then size += @rnd.size end
|
832
|
+
case which when :all, :ary, :nsq, :spr then size += @spr.size end
|
833
|
+
case which when :all, :nsq, :rnd then size += @rnd.size end
|
814
834
|
size
|
815
835
|
end
|
816
836
|
|
@@ -835,14 +855,6 @@ class Sarah
|
|
835
855
|
|
836
856
|
# Sets the negative mode, the manner in which negative integer
|
837
857
|
# index/key values are handled.
|
838
|
-
#
|
839
|
-
# :actual - Negative keys represent themselves and are not treated
|
840
|
-
# specially (although delete works like unset in this mode--values
|
841
|
-
# are not reindexed)
|
842
|
-
# :error (default) - Negative keys are interpreted relative to the
|
843
|
-
# end of the array; keys < -@ary_next raise an IndexError
|
844
|
-
# :ignore - Like :error, but keys < -@ary_next are treated as
|
845
|
-
# non-existent on fetch and silently ignored on set
|
846
858
|
def negative_mode= (mode)
|
847
859
|
case mode
|
848
860
|
when :actual then @negative_mode = :actual
|
@@ -909,6 +921,22 @@ class Sarah
|
|
909
921
|
# @since 2.0.0
|
910
922
|
def rehash; @spr.rehash; @rnd.rehash; self; end
|
911
923
|
|
924
|
+
# Reindex sparse array values sequentially after any existing
|
925
|
+
# sequential values (or else from index 0).
|
926
|
+
#
|
927
|
+
# This is an immediate in-place operation (not a mode) and is unaffected
|
928
|
+
# by the {#negative_mode}.
|
929
|
+
#
|
930
|
+
# @return [Sarah]
|
931
|
+
# @since 2.1.0
|
932
|
+
def reindex
|
933
|
+
if !@spr.empty?
|
934
|
+
@seq.concat values(:spr)
|
935
|
+
@spr, @ary_first, @ary_next = {}, 0, @seq.size
|
936
|
+
end
|
937
|
+
self
|
938
|
+
end
|
939
|
+
|
912
940
|
# #repeated_combination is not implemented.
|
913
941
|
|
914
942
|
# #repeated_permutation is not implemented.
|
@@ -980,19 +1008,22 @@ class Sarah
|
|
980
1008
|
end
|
981
1009
|
end
|
982
1010
|
|
983
|
-
# Return the sparse array and random-access hash (for
|
1011
|
+
# Return a copy of the merged sparse array and random-access hash (for
|
984
1012
|
# backward-compatibility only).
|
985
1013
|
#
|
1014
|
+
# Through version 2.0.0, this returned the actual underlying random-access
|
1015
|
+
# hash.
|
1016
|
+
#
|
986
1017
|
# @return [Hash]
|
987
|
-
# @deprecated Please use {#to_h} instead.
|
988
|
-
def rnd;
|
1018
|
+
# @deprecated Please use {#to_h} :nsq instead.
|
1019
|
+
def rnd; self.to_h :nsq; end
|
989
1020
|
|
990
1021
|
# Return the sparse array and random-access hash values (for
|
991
1022
|
# backward-compatibility only).
|
992
1023
|
#
|
993
1024
|
# @return [Array]
|
994
|
-
# @deprecated Please use {#values} instead.
|
995
|
-
def rnd_values;
|
1025
|
+
# @deprecated Please use {#values} :nsq or #values :rnd instead.
|
1026
|
+
def rnd_values; self.values :nsq; end
|
996
1027
|
|
997
1028
|
# Rotate sequential and sparse array values into a sequential list.
|
998
1029
|
#
|
@@ -1023,9 +1054,11 @@ class Sarah
|
|
1023
1054
|
|
1024
1055
|
# Return a copy of the sequential array values.
|
1025
1056
|
#
|
1057
|
+
# Prior to 2.0.0, this returned the actual underlying array.
|
1058
|
+
#
|
1026
1059
|
# @return [Array]
|
1027
|
-
# @deprecated Please use {#values} instead.
|
1028
|
-
def seq;
|
1060
|
+
# @deprecated Please use {#values} :seq instead.
|
1061
|
+
def seq; self.values :seq; end
|
1029
1062
|
|
1030
1063
|
alias_method :seq_values, :seq
|
1031
1064
|
|
@@ -1202,27 +1235,29 @@ class Sarah
|
|
1202
1235
|
|
1203
1236
|
# Return all or part of the structure in array representation.
|
1204
1237
|
#
|
1205
|
-
# @param which [:all|:ary|:rnd|:seq|:spr] The parts to represent.
|
1238
|
+
# @param which [:all|:ary|:nsq|:rnd|:seq|:spr] The parts to represent.
|
1239
|
+
# (:nsq since 2.1.0)
|
1206
1240
|
# @since 2.0.0
|
1207
1241
|
def to_a (which = :all)
|
1208
1242
|
ary, hsh = [], {}
|
1209
1243
|
case which when :all, :ary, :seq then ary = @seq end
|
1210
|
-
case which when :all, :ary, :spr then hsh.merge! @spr end
|
1211
|
-
case which when :all, :rnd then hsh.merge! @rnd end
|
1244
|
+
case which when :all, :ary, :nsq, :spr then hsh.merge! @spr end
|
1245
|
+
case which when :all, :nsq, :rnd then hsh.merge! @rnd end
|
1212
1246
|
ary + [hsh]
|
1213
1247
|
end
|
1214
1248
|
|
1215
1249
|
# Return all or part of the structure in hash representation.
|
1216
1250
|
#
|
1217
|
-
# @param which [:all|:ary|:rnd|:seq|:spr] The parts to represent.
|
1251
|
+
# @param which [:all|:ary|:nsq|:rnd|:seq|:spr] The parts to represent.
|
1252
|
+
# (:nsq since 2.1.0)
|
1218
1253
|
# @since 2.0.0
|
1219
1254
|
def to_h (which = :all)
|
1220
1255
|
hsh = {}
|
1221
1256
|
case which when :all, :ary, :seq
|
1222
1257
|
@seq.each_index { |i| hsh[i] = @seq[i] }
|
1223
1258
|
end
|
1224
|
-
case which when :all, :ary, :spr then hsh.merge! @spr end
|
1225
|
-
case which when :all, :rnd then hsh.merge! @rnd end
|
1259
|
+
case which when :all, :ary, :nsq, :spr then hsh.merge! @spr end
|
1260
|
+
case which when :all, :nsq, :rnd then hsh.merge! @rnd end
|
1226
1261
|
hsh
|
1227
1262
|
end
|
1228
1263
|
|
@@ -1346,13 +1381,14 @@ class Sarah
|
|
1346
1381
|
|
1347
1382
|
# Return an array of values.
|
1348
1383
|
#
|
1349
|
-
# @param which [:all|:ary|:rnd|:seq|:spr] Which values to return.
|
1350
|
-
# (Since 2.0.0)
|
1384
|
+
# @param which [:all|:ary|:nsq|:rnd|:seq|:spr] Which values to return.
|
1385
|
+
# (Since 2.0.0; :nsq since 2.1.0)
|
1351
1386
|
# @return [Array]
|
1352
1387
|
def values (which = :all)
|
1353
1388
|
case which
|
1354
1389
|
when :all then @seq + values(:spr) + @rnd.values
|
1355
1390
|
when :ary then @seq + values(:spr)
|
1391
|
+
when :nsq then values(:spr) + @rnd.values
|
1356
1392
|
when :rnd then @rnd.values
|
1357
1393
|
when :seq then Array.new @seq
|
1358
1394
|
when :spr then @spr.values_at(*@spr.keys.sort)
|
data/sarah.gemspec
CHANGED
data/test/15v210.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'sarah'
|
3
|
+
|
4
|
+
# Test changes for version 2.1.0:
|
5
|
+
# Addition of :nsq (non-sequential) selector
|
6
|
+
# #seq returns a copy, not the underlying (actually from 2.0.0)
|
7
|
+
# #rnd returns spr + rnd, not underlying rnd
|
8
|
+
# #reindex
|
9
|
+
|
10
|
+
class TestSarah_15 < MiniTest::Unit::TestCase
|
11
|
+
|
12
|
+
def test_nsq
|
13
|
+
s = Sarah[1, 2, 5 => 'five', :a => ?a]
|
14
|
+
assert_equal 2, s.size(:nsq), 'size :nsq'
|
15
|
+
assert_equal [ 5, :a ], s.keys(:nsq), 'keys :nsq'
|
16
|
+
assert_equal [ 'five', ?a ], s.values(:nsq), 'values :nsq'
|
17
|
+
assert_equal [ { 5 => 'five', :a => ?a } ], s.to_a(:nsq), 'to_a :nsq'
|
18
|
+
assert_equal({ 5 => 'five', :a => ?a }, s.to_h(:nsq), 'to_h :nsq')
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_reindex
|
22
|
+
s = Sarah[1, 2, 5 => 'five', :a => ?a]
|
23
|
+
assert_equal [ 1, 2, { 5 => 'five' } ], s.to_a(:ary), 'before reindex'
|
24
|
+
s.reindex
|
25
|
+
assert_equal [ 1, 2, 'five', {} ], s.to_a(:ary), 'after reindex'
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_rnd
|
29
|
+
s = Sarah[1, 2, 5 => 'five', :a => ?a]
|
30
|
+
assert_equal 2, s.rnd_size, 'rnd_size'
|
31
|
+
assert_equal 1, s.size(:rnd), 'size :rnd'
|
32
|
+
r = s.rnd
|
33
|
+
assert_equal({ 5 => 'five', :a => ?a }, r, 'rnd returns to_h :nsq')
|
34
|
+
r[5], r[:a] = 'six', ?b
|
35
|
+
assert r != s.rnd, "rnd changes don't affect original"
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_seq
|
39
|
+
s = Sarah[1, 2, 5 => 5, :a => :a]
|
40
|
+
seq = s.seq
|
41
|
+
seq[0], seq[1] = 3, 4
|
42
|
+
assert seq != s.seq, "seq changes don't affect original"
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
# END
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 2
|
7
|
-
- 0
|
8
7
|
- 1
|
9
|
-
|
8
|
+
- 0
|
9
|
+
version: 2.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Brian Katzung
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2014-04-
|
17
|
+
date: 2014-04-10 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -50,6 +50,7 @@ files:
|
|
50
50
|
- test/00class.rb
|
51
51
|
- test/08set_ops.rb
|
52
52
|
- test/10count_size.rb
|
53
|
+
- test/15v210.rb
|
53
54
|
- test/13misc.rb
|
54
55
|
- test/05class2.rb
|
55
56
|
- test/06instance2.rb
|
@@ -98,6 +99,7 @@ test_files:
|
|
98
99
|
- test/00class.rb
|
99
100
|
- test/08set_ops.rb
|
100
101
|
- test/10count_size.rb
|
102
|
+
- test/15v210.rb
|
101
103
|
- test/13misc.rb
|
102
104
|
- test/05class2.rb
|
103
105
|
- test/06instance2.rb
|