1Array::IntSpan(3) User Contributed Perl Documentation Array::IntSpan(3)
2
3
4
6 Array::IntSpan - Handles arrays of scalars or objects using integer
7 ranges
8
10 use Array::IntSpan;
11
12 my $foo = Array::IntSpan->new([0, 59, 'F'], [60, 69, 'D'], [80, 89, 'B']);
13
14 print "A score of 84% results in a ".$foo->lookup(84).".\n";
15 unless (defined($foo->lookup(70))) {
16 print "The grade for the score 70% is currently undefined.\n";
17 }
18
19 $foo->set_range(70, 79, 'C');
20 print "A score of 75% now results in a ".$foo->lookup(75).".\n";
21
22 $foo->set_range(0, 59, undef);
23 unless (defined($foo->lookup(40))) {
24 print "The grade for the score 40% is now undefined.\n";
25 }
26
27 $foo->set_range(87, 89, 'B+');
28 $foo->set_range(85, 100, 'A');
29 $foo->set_range(100, 1_000_000, 'A+');
30
32 "Array::IntSpan" brings the speed advantages of "Set::IntSpan" (written
33 by Steven McDougall) to arrays. Uses include manipulating grades,
34 routing tables, or any other situation where you have mutually
35 exclusive ranges of integers that map to given values.
36
37 The new version of "Array::IntSpan" is also able to consolidate the
38 ranges by comparing the adjacent values of the range. If 2 adjacent
39 values are identical, the 2 adjacent ranges are merged.
40
42 "Array::IntSpan" can also handle objects instead of scalar values.
43
44 But for the consolidation to work, the payload class must overload the
45 "", "eq" and "==" operators to perform the consolidation comparisons.
46
47 When a get_range method is called to a range of objects, it will return
48 a new range of object referencess. These object references points to
49 the objects stored in the original range. In other words the objects
50 contained in the returned range are not copied.
51
52 Thus if the user calls a methods on the objects contained in the
53 returned range, the method is actually invoked on the objects stored in
54 the original range.
55
56 When a get_range method is called on a range of objects, several things
57 may happen:
58
59 • The get_range spans empty slots. By default the returned range will
60 skip the empty slots. But the user may provide a callback to create
61 new objects (for instance). See details below.
62
63 • The get_range splits existing ranges. By default, the split range
64 will contains the same object reference. The user may provide
65 callback to perform the object copy so that the split range will
66 contains different objects. See details below.
67
69 • "Array::IntSpan::IP" is also provided with the distribution. It
70 lets you use IP addresses in any of three forms (dotted decimal,
71 network string, and integer) for the indices into the array. See
72 the POD for that module for more information. See
73 Array::IntSpan::IP for details.
74
75 • "Array::IntSpan::Fields" is also provided with the distribution. It
76 let you specify an arbitrary specification to handle ranges with
77 strings made of several integer separared by dots (like IP
78 addresses of ANSI SS7 point codes). See Array::IntSpan::Fields for
79 details.
80
82 new (...)
83 The "new" method takes an optional list of array elements. The
84 elements should be in the form "[start_index, end_index, value]". They
85 should be in sorted order and there should be no overlaps. The
86 internal method "_check_structure" will be called to verify the data is
87 correct. If you wish to avoid the performance penalties of checking
88 the structure, you can use "Data::Dumper" to dump an object and use
89 that code to reconstitute it.
90
91 clear
92 Clear the range.
93
94 set_range (start, end, value [, code ref] )
95 This method takes three parameters - the "start_index", the
96 "end_index", and the "value". If you wish to erase a range, specify
97 "undef" for the "value". It properly deals with overlapping ranges and
98 will replace existing data as appropriate. If the new range lies after
99 the last existing range, the method will execute in O(1) time. If the
100 new range lies within the existing ranges, the method executes in O(n)
101 time, where n is the number of ranges. It does not consolidate
102 contiguous ranges that have the same "value".
103
104 If you have a large number of inserts to do, it would be beneficial to
105 sort them first. Sorting is O(n lg(n)), and since appending is O(1),
106 that will be considerably faster than the O(n^2) time for inserting n
107 unsorted elements.
108
109 The method returns 0 if there were no overlapping ranges and 1 if there
110 were.
111
112 The optional code ref is called back when an existing range is split.
113 For instance if the original range is "[0,10,$foo_obj]" and set_range
114 is called with "[5,7,$bar_obj']", the callback will be called twice:
115
116 $callback->(0, 4,$foo_obj)
117 $callback->(8,10,$foo_obj)
118
119 It will be the callback responsability to make sure that the range
120 "0-4" and "7-10" holds 2 different objects.
121
122 set( index, value [, code ref] )
123 Set a single value. This may split an existing range. Actually calls:
124
125 set_range( index, index, value [, code ref] )
126
127 set_range_as_string ( index, string [, code ref] )
128 Set one one several ranges specified with a string. Ranges are
129 separated by "-". Several ranges can be specified with commas.
130
131 Example:
132
133 set_range_as_string( '1-10,13, 14-20', 'foo')
134
135 White space are ignored.
136
137 get_range (start, end [, filler | undef , copy_cb [, set_cb]])
138 This method returns a range (actually an Array::IntSpan object) from
139 "start" to "end".
140
141 If "start" and "end" span empty slot in the original range, get_range
142 will skip the empty slots. If a "filler" value is provided, get_range
143 will fill the slots with it.
144
145 original range : [2-4,X],[7-9,Y],[12-14,Z]
146 get_range(3,8) : [3-4,X],[7-8,Y]
147 get_range(2,10,f) : [3-4,X],[5-6,f],[7-8,Y]
148
149 If the "filler" parameter is a CODE reference, the filler value will be
150 the one returned by the sub ref. The sub ref is invoked with
151 "(start,end)", i.e. the range of the empty span to fill
152 ("get_range(5,6)" in the example above). When handling object, the sub
153 ref can invoke an object constructor.
154
155 If "start" or "end" split an original range in 2, the default behavior
156 is to copy the value or object ref contained in the original range:
157
158 original range : [1-4,X]
159 split range : [1-1,X],[2-2,X],[3-4,X]
160 get_range(2) : [2-2,X]
161
162 If the original range contains object, this may lead to disapointing
163 results. In the example below the 2 ranges contains references
164 ("obj_a") that points to the same object:
165
166 original range : [1-4,obj_a]
167 split range : [1-1,obj_a],[2-2,obj_a],[3-4,obj_a]
168 get_range(2) : [2-2,obj_a]
169
170 Which means that invoking a method on the object returned by
171 get_range(2) will also be invoked on the range 1-4 of the original
172 range which may not be what you want.
173
174 If "get_range" is invoked with a copy parameter (actually a code
175 reference), the result of this routine will be stored in the split
176 range outside of the get_range:
177
178 original range : [1-4,X]
179 get_range(2) : [2-2,X]
180 split range : [1-1,copy_of_X],[2-2,X],[3-4,copy_of_X]
181
182 When dealing with object, the sub ref should provide a copy of the
183 object:
184
185 original range : [1-4,obj_a]
186 get_range(2) : [2-2,obj_a]
187 split range : [1-1,obj_a1],[2-2,obj_a],[3-4,obj_a2]
188
189 Note that the "obj_a" contained in the "split range" and the "obj_a"
190 contained in the returned range point to the same object.
191
192 The sub ref is invoked with "(start,end,obj_a)" and is expected to
193 return a copy of "obj_a" that will be stored in the split ranges. In
194 the example above, 2 different copies are made: "obj_a1" and "obj_a2".
195
196 Last, a 3rd callback may be defined by the user: the "set_cb". This
197 callback will be used when the range start or end that holds an object
198 changes. In the example above, the "set_cb" will be called this way:
199
200 $obj_a->&$set_cb(2,2) ;
201
202 As a matter of fact, the 3 callback can be used in the same call. In
203 the example below, "get_range" is invoked with 3 subs refs:
204 "\&f,\&cp,\&set":
205
206 original range : [1-4,obj_a],[7-9,obj_b]
207 get_range(3-8,...) : [3-4,obj_a],[5-6,obj_fill],[7-8,obj_b]
208 split range : [1-2,obj_a1], [3-4,obj_a],[5-6,obj_fill],
209 [7-8,obj_b],[9-9,obj_b1]
210
211 To obtain this, get_range will perform the following calls:
212
213 $obj_fill = &f ;
214 $obj_a1 = &cp(5,6,obj_a);
215 &set(3,4,$obj_a) ;
216 $obj_b = &cp(9,9,obj_b) ;
217 &set(7-8,obj_b) ;
218
219 get_range_list
220 In scalar context, returns a list of range in a string like:
221 ""1-5,7,9-11"".
222
223 In list context retunrs a list of list, E.g. " ( [1,5], [7,7], 9,11])".
224
225 lookup( index )
226 This method takes as a single parameter the "index" to look up. If
227 there is an appropriate range, the method will return the associated
228 value. Otherwise, it returns "undef".
229
230 get_element( element_number )
231 Returns an array containing the Nth range element:
232
233 ( start, end, value )
234
235 consolidate( [ bottom, top , [ set_cb ]] )
236 This function scans the range from the range index "bottom" to "top"
237 and compare the values held by the adjacent ranges. If the values are
238 identical, the adjacent ranges are merged.
239
240 The comparison is made with the "==" operator. Objects stored in the
241 range must overload the "==" operator. If not, the comparison is made
242 with the standard stringification of an object and the merge never
243 happens.
244
245 If provided, the "set_cb" is invoked on the contained object after 2
246 ranges are merged.
247
248 For instance, if "$obj_a" eq "$obj_b":
249
250 original range is : [1-4,obj_a],[5-9,obj_b]
251 consolidate(0,1,\&set) yields: [1-9,obj_a]
252
253 And "consolidate" performs this call:
254
255 $set->(1,9,obj_a) ;
256
257 Consolidate the whole range when called without parameters.
258
260 • Mohammad S Anwar <mohammad.anwar@yahoo.com>
261
263 • Toby Everett, teverett@alascom.att.com
264
265 • Dominique Dumont, ddumont@cpan.org
266
267 Copyright (c) 2000 Toby Everett. Copyright (c) 2003-2004,2014,2020
268 Dominique Dumont. All rights reserved. This program is free software.
269
270 This module is distributed under the Artistic 2.0 License. See
271 https://www.perlfoundation.org/artistic-license-20.html
272
273
274
275perl v5.36.0 2023-01-19 Array::IntSpan(3)