sarah 2.0.1 → 2.1.0

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