sarah 2.0.1 → 2.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.
Files changed (5) hide show
  1. data/HISTORY.txt +11 -0
  2. data/lib/sarah.rb +82 -46
  3. data/sarah.gemspec +2 -2
  4. data/test/15v210.rb +47 -0
  5. metadata +5 -3
@@ -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.
@@ -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
- # All three parts together are collectively referred to as "all".
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.0.0
63
+ # @version 2.1.0
62
64
 
63
65
  class Sarah
64
66
 
65
- VERSION = "2.0.0"
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. Possible values are
91
- # :actual, :error, and :ignore. See {#negative_mode=}.
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=} :actual.
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; @rnd.keys; end
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; 0...@seq.size; end
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
- # @deprecated Please use {#size} instead.
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; @rnd.size; end
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; @rnd; end
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; @spr.values + @rnd.values; end
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; Array.new(@seq); end
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)
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "sarah"
3
- s.version = "2.0.1"
4
- s.date = "2014-04-01"
3
+ s.version = "2.1.0"
4
+ s.date = "2014-04-10"
5
5
  s.authors = ["Brian Katzung"]
6
6
  s.email = ["briank@kappacs.com"]
7
7
  s.homepage = "http://rubygems.org/gems/sarah"
@@ -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
- version: 2.0.1
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-01 00:00:00 -05:00
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