COVERAGE SUMMARY
FILE SUMMARY
NameExecutedRoutines%ExecutedLines%Unexecuted
/home/matt/eu/rds/include/std/sequence.e394097.50%70073495.37%34
ROUTINE SUMMARY
RoutineExecutedLinesUnexecuted
add_item()0100.00%10
columnize()253083.33%5
mapping()101376.92%3
breakup()464895.83%2
build_list()222491.67%2
rotate()151788.24%2
vslice()182090.00%2
can_add()91090.00%1
extract()7887.50%1
fetch()7887.50%1
mid()111291.67%1
patch()111291.67%1
split()484997.96%1
split_any()303196.77%1
store()181994.74%1
apply()55100.00%0
combine()1818100.00%0
filter()110110100.00%0
filter_alpha()22100.00%0
flatten()1919100.00%0
join()88100.00%0
linear()99100.00%0
minsize()44100.00%0
pad_head()44100.00%0
pad_tail()44100.00%0
pivot()99100.00%0
project()88100.00%0
remove_all()1919100.00%0
remove_dups()2424100.00%0
remove_item()99100.00%0
remove_subseq()1919100.00%0
repeat_pattern()1010100.00%0
replace_all()1515100.00%0
retain_all()1818100.00%0
reverse()2121100.00%0
shuffle()88100.00%0
sim_index()3737100.00%0
slice()1010100.00%0
transform()1010100.00%0
valid_index()88100.00%0
LINE COVERAGE DETAIL
#Executed
1
-- (c) Copyright - See License.txt
2
--
3
namespace stdseq
4
5
--****
6
-- == Sequence Manipulation
7
--
8
-- <>
9
include std/error.e
10
include std/search.e
11
12
include std/sort.e
13
include std/math.e
14
include std/types.e
15
16
--****
17
-- === Constants
18
19
public enum
20101
ADD_PREPEND,
21101
ADD_APPEND,
22101
ADD_SORT_UP,
23101
ADD_SORT_DOWN
24
25
public constant
26101
ROTATE_LEFT = 1,
27101
ROTATE_RIGHT = -1
28
29
--****
30
-- === Basic routines
31
--
32
33
--**
34
-- Checks whether two objects can be legally added together.
35
--
36
-- Parameters:
37
-- # ##a## : one of the objects to test for compatible shape
38
-- # ##b## : the other object
39
--
40
-- Returns:
41
-- An **integer**, 1 if an addition (or any of the [[:Relational operators]])
42
-- are possible between ##a## and ##b##, else 0.
43
--
44
-- Example 1:
45
--
46
-- i = can_add({1,2,3},{4,5})
47
-- -- i is 0
48
--
49
-- i = can_add({1,2,3},4)
50
-- -- i is 1
51
--
52
-- i = can_add({1,2,3},{4,{5,6},7})
53
-- -- i is 1
54
--
55
--
56
-- See Also:
57
-- [[:linear]]
58
597
607
if atom(a) or atom(b) then
614
return 1
62
end if
633
if length(a)!=length(b) then
641
return 0
65
end if
662
for i=1 to length(a) do
674
if not can_add(a[i], b[i]) then
680
return 0
69
end if
704
end for
712
return 1
72
end function
73
74
--**
75
-- Retrieves an element nested arbitrarily deep into a sequence.
76
--
77
-- Parameters:
78
-- # ##source## : the sequence from which to fetch
79
-- # ##indexes## : a sequence of integers, the path to follow to reach the
80
-- element to return.
81
--
82
-- Returns:
83
-- An **object**, which is ##source[indexes[1]][indexes[2]]...[indexes[$]]##
84
--
85
-- Errors:
86
-- If the path cannot be followed to its end, an error about reading a
87
-- nonexistent element, or subscripting an atom, will occur.
88
--
89
-- Comments:
90
-- The last element of ##indexes## may be a pair {lower,upper}, in which case
91
-- a slice of the innermost referenced sequence is returned.
92
--
93
-- Example 1:
94
--
95
-- x = fetch({0,1,2,3,{"abc","def","ghi"},6},{5,2,3})
96
-- -- x is 'f', or 102.
97
--
98
--
99
-- See Also:
100
-- [[:store]], [[:Subscripting of Sequences]]
101
1021
103
object x
104
1051
for i=1 to length(indexes)-1 do
1062
source = source[indexes[i]]
1072
end for
1081
x = indexes[$]
1091
if atom(x) then
1101
return source[x]
111
else
1120
return source[x[1]..x[2]]
113
end if
114
end function
115
116
--**
117
-- Stores something at a location nested arbitrarily deep into a sequence.
118
--
119
-- Parameters:
120
-- # ##target## : the sequence in which to store something
121
-- # ##indexes## : a sequence of integers, the path to follow to reach the
122
-- place where to store
123
-- # ##x## : the object to store.
124
--
125
-- Returns:
126
-- A **sequence**, a **copy** of ##target## with the specified place
127
-- ##indexes## modified by storing ##x## into it.
128
--
129
-- Errors:
130
-- If the path to storage location cannot be followed to its end, or an
131
-- index is not what one would expect or is not valid, an error about illegal
132
-- sequence operations will occur.
133
--
134
-- Comments:
135
-- If the last element of ##indexes## is a pair of integers, ##x## will be
136
-- stored as a slice three, the bounding indexes being given in the pair as {lower,upper}..
137
--
138
-- In Euphoria, you can never modify an object by passing it to a routine.
139
-- You have to get a modified copy and then assign it back to the original.
140
--
141
-- Example 1:
142
--
143
-- s = store({0,1,2,3,{"abc","def","ghi"},6},{5,2,3},108)
144
-- -- s is {0,1,2,3,{"abc","del","ghi"},6}
145
--
146
--
147
-- See Also:
148
-- [[:fetch]], [[:Subscripting of Sequences]]
149
1501
151
sequence partials,result,branch
152
object last_idx
153
1541
partials = repeat(target,length(indexes)-1)
1551
branch = target
1561
for i=1 to length(indexes)-1 do
1572
branch=branch[indexes[i]]
1582
partials[i]=branch
1592
end for
160
1611
last_idx = indexes[$]
1621
if atom(last_idx) then
1631
branch[last_idx]=x
164
else
1650
branch[last_idx[1]..last_idx[2]]=x
166
end if
167
1681
partials = prepend(partials,0) -- avoids computing temp=i+1 a few times
169
1701
for i=length(indexes)-1 to 2 by -1 do
1711
result = partials[i]
1721
result[indexes[i]] = branch
1731
branch = result
1741
end for
1751
target[indexes[1]] = branch
1761
return target
177
end function
178
179
--**
180
-- Checks whether an index exists on a sequence.
181
--
182
-- Parameters:
183
-- # ##s## : the sequence for which to check
184
-- # ##x## : an object, the index to check.
185
--
186
-- Returns:
187
-- An **integer**, 1 if ##s[x]## makes sense, else 0.
188
--
189
-- Example 1:
190
--
191
-- i = valid_index({51,27,33,14},2)
192
-- -- i is 1
193
--
194
--
195
-- See Also:
196
-- [[:Subscripting of Sequences]]
197
19883
19983
if not atom(x) then
2002
return 0
201
end if
20281
if x < 1 then
2033
return 0
204
end if
20578
if floor(x) > length(st) then
2062
return 0
207
end if
20876
return 1
209
end function
210
211
--**
212
-- Rotates a slice of a sequence.
213
--
214
-- Parameters:
215
-- # ##source## : sequence to be rotated
216
-- # ##shift## : direction and count to be shifted (##ROTATE_LEFT## or ##ROTATE_RIGHT##)
217
-- # ##start## : starting position for shift, defaults o 1
218
-- # ##stop## : stopping position for shift, defaults to ##length(source)##
219
--
220
-- Comments:
221
--
222
-- Use ##amount * direction## to specify the shift. direction is either ##ROTATE_LEFT##
223
-- or ##ROTATE_RIGHT##. This enables to shift multiple places in a single call.
224
-- For instance, use {{{ROTATE_LEFT * 5}}} to rotate left, 5
225
-- positions.
226
--
227
-- A null shift does nothing and returns source unchanged.
228
--
229
-- Example 1:
230
--
231
-- s = rotate({1, 2, 3, 4, 5}, ROTATE_LEFT)
232
-- -- s is {2, 3, 4, 5, 1}
233
--
234
--
235
-- Example 2:
236
--
237
-- s = rotate({1, 2, 3, 4, 5}, ROTATE_RIGHT * 2)
238
-- -- s is {4, 5, 1, 2, 3}
239
--
240
--
241
-- Example 3:
242
--
243
-- s = rotate({11,13,15,17,19,23}, ROTATE_LEFT, 2, 5)
244
-- -- s is {11,15,17,19,13,23}
245
--
246
--
247
-- Example 4:
248
--
249
-- s = rotate({11,13,15,17,19,23}, ROTATE_RIGHT, 2, 5)
250
-- -- s is {11,19,13,15,17,23}
251
--
252
--
253
-- See Also:
254
-- [[:slice]], [[:head]], [[:tail]]
255
25616
257
sequence shifted
258
integer len
259
integer lSize
260
26116
if start >= stop or length(source)=0 or not shift then
2624
return source
263
end if
264
26512
if not valid_index(source, start) then
2660
crash("sequence:rotate(): invalid 'start' parameter %d", start)
267
end if
268
26912
if not valid_index(source, stop) then
2700
crash("sequence:rotate(): invalid 'stop' parameter %d", stop)
271
end if
272
27312
len = stop - start + 1
27412
lSize = remainder(shift, len)
27512
if lSize = 0 then
2762
return source
277
end if
278
27910
if lSize < 0 then -- convert right shift to left shift
2805
lSize += len
281
end if
282
28310
shifted = source[start .. start + lSize-1]
28410
source[start .. stop - lSize] = source[start + lSize .. stop]
28510
source[stop - lSize + 1.. stop] = shifted
28610
return source
287
end function
288
289
--**
290
-- Converts a set of sub sequences into a set of 'columns'.
291
--
292
-- Parameters:
293
-- # ##source## : sequence containing the sub-sequences
294
-- # ##cols## : either a specific column number or a set of column numbers.
295
-- Default is 0, which returns the maximum number of columns.
296
-- # ##defval## : an object. Used when a column value is not available. Default is 0
297
--
298
-- Comments:
299
-- Any atoms found in ##source## are treated as if they are a 1-element sequence.
300
--
301
-- Example 1:
302
--
303
-- s = columnize({{1, 2}, {3, 4}, {5, 6}})
304
-- -- s is { {1,3,5}, {2,4,6}}
305
--
306
--
307
-- Example 2:
308
--
309
-- s = columnize({{1, 2}, {3, 4}, {5, 6, 7}})
310
-- -- s is { {1,3,5}, {2,4,6}, {0,0,7} }
311
-- s = columnize({{1, 2}, {3, 4}, {5, 6, 7},,-999}) -- Change the not-available value.
312
-- -- s is { {1,3,5}, {2,4,6}, {-999,-999,7} }
313
--
314
--
315
-- Example 3:
316
--
317
-- s = columnize({{1, 2}, {3, 4}, {5, 6, 7}}, 2)
318
-- -- s is { {2,4,6} } -- Column 2 only
319
--
320
--
321
-- Example 4:
322
--
323
-- s = columnize({{1, 2}, {3, 4}, {5, 6, 7}}, {2,1})
324
-- -- s is { {2,4,6}, {1,3,5} } -- Column 2 then column 1
325
--
326
--
327
-- Example 5:
328
--
329
-- s = columnize({"abc", "def", "ghi"})
330
-- -- s is {"adg", "beh", "cfi" }
331
--
332
333
3348
335
sequence result
336
sequence collist
337
3388
if sequence(cols) then
3397
collist = cols
340
else
3411
collist = {cols}
342
end if
343
3448
if length(collist) = 0 then
3456
cols = 0
3466
for i = 1 to length(source) do
34717
if atom(source[i]) then
3480
if cols = 0 then
3490
cols = 1
350
end if
351
else
35217
if cols < length(source[i]) then
3538
cols = length(source[i])
354
end if
355
end if
35617
end for
3576
for i = 1 to cols do
35816
collist &= i
35916
end for
360
end if
361
3628
result = repeat({}, length(collist))
3638
for i = 1 to length(collist) do
36419
integer col = collist[i]
36519
for j = 1 to length(source) do
36655
if atom(source[j]) then
3670
if 1 < col then
3680
result[i] = append(result[i], defval)
369
else
3700
result[i] = append(result[i], source[j][col])
371
end if
372
else
37355
if length(source[j]) < col then
3745
result[i] = append(result[i], defval)
375
else
37650
result[i] = append(result[i], source[j][col])
377
end if
378
end if
37955
end for
38019
end for
381
3828
return result
383
end function
384
385
386
--**
387
-- Apply a function to every element of a sequence returning a new sequence of
388
-- the same size.
389
--
390
-- Parameters:
391
-- * ##source## : the sequence to map
392
-- * ##rid## : the [[:routine_id]] of function to use as converter
393
-- * ##userdata## : an object passed to each invocation of ##rid##. If omitted,
394
-- {} is used.
395
--
396
-- Returns:
397
-- A **sequence**, the length of ##source##. Each element there is the
398
-- corresponding element in ##source## mapped using the routine referred to by ##rid##.
399
--
400
-- Comments:
401
-- The supplied routine must take two parameters. The type of the first parameter must
402
-- be compatible with all the elements in ##source##. The second parameter is
403
-- an ##object## containing ##userdata##.
404
--
405
-- Example 1:
406
--
407
-- function greeter(object o, object d)
408
-- return o[1] & ", " & o[2] & d
409
-- end function
410
--
411
-- s = apply({{"Hello", "John"}, {"Goodbye", "John"}}, routine_id("greeter"), "!")
412
-- -- s is {"Hello, John!", "Goodbye, John!"}
413
--
414
--
415
-- See Also:
416
-- [[:filter]]
417
4181
4191
for a = 1 to length(source) do
4204
source[a] = call_func(rid, {source[a], userdata})
4214
end for
4221
return source
423
end function
424
425
--**
426
-- Each item from ##source_arg## found in ##from_set## is changed into the
427
-- corresponding item in ##to_set##
428
--
429
-- Parameters:
430
-- # ##source_arg## : Any Euphoria object to be transformed.
431
-- # ##from_set## : A sequence of objects representing the only items from
432
-- ##source_arg## that are actually transformed.
433
-- # ##to_set## : A sequence of objects representing the transformed equivalents
434
-- of those found in ##from_set##.
435
-- # ##one_level## : An integer. 0 (the default) means that mapping applies to
436
-- every atom in every level of sub-sequences. 1 means that
437
-- mapping only applies to the items at the first level
438
-- in ##source_arg##.
439
--
440
-- Returns:
441
-- An **object**, The transformed version of ##source_arg##.
442
--
443
-- Comments:
444
-- * When ##one_level## is zero or omitted, for each item in ##source_arg##,
445
-- ** if it is an atom then it may be transformed
446
-- ** if it is a sequence, then the mapping is performed recursively on the
447
-- sequence.
448
-- ** This option required ##from_set## to only contain atoms and contain no
449
-- sub-sequences.
450
-- * When ##one_level## is not zero, for each item in ##source_arg##,
451
-- ** regardless of whether it is an atom or sequence, if it is found in ##from_set##
452
-- then it is mapped to the corresponding object in ##to_set##..
453
-- * Mapping occurs when an item in ##source_arg## is found in ##from_set##,
454
-- then it is replaced by the corresponding object in ##to_set##.
455
--
456
-- Example 1:
457
--
458
-- res = mapping("The Cat in the Hat", "aeiou", "AEIOU")
459
-- -- res is now "ThE CAt In thE HAt"
460
--
461
46210
463
integer pos
464
46510
if atom(source_arg) then
4660
pos = find(source_arg, from_set)
4670
if pos >= 1 and pos <= length(to_set) then
4680
source_arg = to_set[pos]
469
end if
470
else
47110
for i = 1 to length(source_arg) do
472161
if atom(source_arg[i]) or one_level then
473160
pos = find(source_arg[i], from_set)
474160
if pos >= 1 and pos <= length(to_set) then
47590
source_arg[i] = to_set[pos]
476
end if
477
else
4781
source_arg[i] = mapping(source_arg[i], from_set, to_set)
479
end if
480161
end for
481
end if
482
48310
return source_arg
484
end function
485
486
--****
487
-- Signature:
488
-- function length(sequence target)
489
--
490
-- Description:
491
-- Return the length of a sequence.
492
--
493
-- Parameters:
494
-- # ##target## : the sequence being queried
495
--
496
-- Returns:
497
-- An **integer**, the number of elements ##target## has.
498
--
499
-- Comments:
500
-- The length of each sequence is stored internally by the
501
-- interpreter for fast access. In some other languages this
502
-- operation requires a search through memory for an end marker.
503
--
504
-- Example 1:
505
--
506
-- length({{1,2}, {3,4}, {5,6}}) -- 3
507
-- length("") -- 0
508
-- length({}) -- 0
509
--
510
--
511
-- See Also:
512
-- [[:append]], [[:prepend]], [[:& -> amp_concat]]
513
514
--**
515
-- Reverse the order of elements in a sequence.
516
--
517
-- Parameters:
518
-- # ##target## : the sequence to reverse.
519
-- # ##pFrom## : an integer, the starting point. Defaults to 1.
520
-- # ##pTo## : an integer, the end point. Defaults to 0.
521
--
522
-- Returns:
523
-- A **sequence**, if ##target## is a sequence, the same length as ##target##
524
-- and the same elements, but those with index between ##pFrom## and ##pTo##
525
-- appear in reverse order.
526
--
527
-- Comments:
528
-- In the result sequence, some or all top-level elements appear in reverse order compared
529
-- to the original sequence. This does not reverse any sub-sequences found in the original
530
-- sequence.\\
531
-- The ##pTo## parameter can be negative, which indicates an offset from the last element.
532
-- Thus {{{-1}}} means the second-last element and {{{0}}} means the last element.
533
--
534
-- Example 1:
535
--
536
-- reverse({1,3,5,7}) -- {7,5,3,1}
537
-- reverse({1,3,5,7,9}, 2, -1) -- {1,7,5,3,9}
538
-- reverse({1,3,5,7,9}, 2) -- {1,9,7,5,3}
539
-- reverse({{1,2,3}, {4,5,6}}) -- {{4,5,6}, {1,2,3}}
540
-- reverse({99}) -- {99}
541
-- reverse({}) -- {}
542
-- reverse(42) -- 42
543
--
544
54521
546
integer uppr, n, lLimit
547
sequence t
548
54921
if atom(target) or length(target) < 2 then
5503
return target
551
end if
552
55318
n = length(target)
55418
if pFrom < 1 then
5551
pFrom = 1
556
end if
55718
if pTo < 1 then
55816
pTo = n + pTo
559
end if
56018
if pTo < pFrom or pFrom >= n then
5612
return target
562
end if
56316
if pTo > n then
5641
pTo = n
565
end if
566
56716
lLimit = floor((pFrom+pTo-1)/2)
56816
t = target
56916
uppr = pTo
57016
for lowr = pFrom to lLimit do
571117
t[uppr] = target[lowr]
572117
t[lowr] = target[uppr]
573117
uppr -= 1
574117
end for
57516
return t
576
end function
577
578
--**
579
-- Shuffle the elements of a sequence.
580
--
581
-- Parameters:
582
-- # ##seq##: the sequence to shuffle.
583
--
584
-- Returns:
585
-- A **sequence**
586
--
587
-- Comments:
588
-- The input sequence does not have to be in any specific order and can
589
-- contain duplicates. The output will be in an unpredictable order, which
590
-- might even be the same as the input order.
591
--
592
-- Example 1:
593
--
594
-- shuffle({1,2,3,3}) -- {3,1,3,2}
595
-- shuffle({1,2,3,3}) -- {2,3,1,3}
596
-- shuffle({1,2,3,3}) -- {1,2,3,3}
597
--
598
5991
600
-- 1963 shuffle algorithm written by L.E. Moses and R.V. Oakford
601
6021
for toIdx = length(seq) to 2 by -1 do
603
-- Get a random spot in the remaining items
6049
integer fromIdx = rand(toIdx)
605
606
-- Swap the newly picked item with whatever is at the receiving spot
6079
object swapValue = seq[fromIdx]
608
6099
seq[fromIdx] = seq[toIdx]
6109
seq[toIdx] = swapValue
611
6129
end for
613
6141
return seq
615
end function
616
617
--****
618
-- === Building sequences
619
--
620
621
--**
622
-- Returns a sequence in arithmetic progression.
623
--
624
-- Parameters:
625
-- # ##start## : the initial value from which to start
626
-- # ##increment## : the value to recursively add to ##start## to get new elements
627
-- # ##count## : an integer, the number of additions to perform.
628
--
629
-- Returns:
630
-- An **object**, either 0 on failure or
631
-- ##{start, start+increment,...,start+count*increment}##
632
--
633
-- Comments:
634
--
635
-- If ##count## is negative, or if adding ##start## to ##increment## would
636
-- prove to be impossible, then 0 is returned. Otherwise, a sequence, of length
637
-- ##count+1##, staring with ##start## and whose adjacent elements differ
638
-- exactly by ##increment##, is returned.
639
--
640
-- Example 1:
641
--
642
-- s = linear({1,2,3},4,3)
643
-- -- s is {{1,2,3},{5,6,7},{9,10,11}}
644
--
645
--
646
-- See Also:
647
-- [[:repeat_pattern]]
648
6492
650
sequence result
651
6522
if count<0 or not can_add(start,increment) then
6531
return 0
654
end if
6551
result=repeat(start,count)
6561
for i=2 to count do
6573
start += increment
6583
result[i] = start
6593
end for
6601
return result
661
end function
662
663
--**
664
-- Returns a periodic sequence, given a pattern and a count.
665
--
666
-- Parameters:
667
-- # ##pattern## : the sequence whose elements are to be repeated
668
-- # ##count## : an integer, the number of times the pattern is to be repeated.
669
--
670
-- Returns:
671
-- A **sequence**, empty on failure, and of length ##count*length(pattern)##
672
-- otherwise. The first elements of the returned sequence are those of
673
-- ##pattern##. So are those that follow, on to the end.
674
--
675
-- Example 1:
676
--
677
-- s = repeat_pattern({1,2,5},3)
678
-- -- s is {1,2,5,1,2,5,1,2,5}
679
--
680
--
681
-- See Also:
682
-- [[:repeat]], [[:linear]]
683
6842
685
integer ls
686
sequence result
687
6882
if count<=0 then
6891
return {}
690
end if
6911
ls = length(pattern)
6921
count *= ls
6931
result=repeat(0,count)
6941
for i=1 to count by ls do
6954
result[i..i+ls-1] = pattern
6964
end for
6971
return result
698
end function
699
700
--****
701
-- Signature:
702
-- function repeat(object item, atom count)
703
--
704
-- Description:
705
-- Create a sequence whose all elements are identical, with given length.
706
--
707
-- Parameters:
708
-- # ##item## : an object, to which all elements of the result will be equal
709
-- # ##count## : an atom, the requested length of the result sequence. This must
710
-- be a value from zero to 0x3FFFFFFF. Any floating point values
711
-- are first floored.
712
--
713
-- Returns:
714
-- A **sequence**, of length ##count## each element of which is ##item##.
715
--
716
-- Errors:
717
-- ##count## cannot be less than zero and cannot be greater than 1,073,741,823.
718
--
719
-- Comments:
720
-- When you repeat() a sequence or a floating-point number the
721
-- interpreter does not actually make multiple copies in memory.
722
-- Rather, a single copy is "pointed to" a number of times.
723
--
724
-- Example 1:
725
--
726
-- repeat(0, 10) -- {0,0,0,0,0,0,0,0,0,0}
727
--
728
-- repeat("JOHN", 4) -- {"JOHN", "JOHN", "JOHN", "JOHN"}
729
-- -- The interpreter will create only one copy of "JOHN"
730
-- -- in memory and create a sequence containing four references to it.
731
--
732
--
733
-- See Also:
734
-- [[:repeat_pattern]], [[:linear]]
735
736
--****
737
-- === Adding to sequences
738
--
739
740
--****
741
-- Signature:
742
-- function append(sequence target, object x)
743
--
744
-- Description:
745
-- Adds an object as the last element of a sequence.
746
--
747
-- Parameters:
748
-- # ##source## : the sequence to add to
749
-- # ##x## : the object to add
750
--
751
-- Returns:
752
-- A **sequence**, whose first elements are those of ##target## and whose
753
-- last element is ##x##.
754
--
755
-- Comments:
756
--
757
-- The length of the resulting sequence will be ##length(target) + 1##, no
758
-- matter what ##x## is.
759
--
760
-- If ##x## is an atom this is equivalent to ##result = target & x##. If ##x##
761
-- is a sequence it is not equivalent.
762
--
763
-- The extra storage is allocated automatically and very efficiently with
764
-- Euphoria's dynamic storage allocation. The case where ##target## itself is
765
-- append()ed to (as in Example 1 below) is highly optimized.
766
--
767
-- Example 1:
768
--
769
-- sequence x
770
--
771
-- x = {}
772
-- for i = 1 to 10 do
773
-- x = append(x, i)
774
-- end for
775
-- -- x is now {1,2,3,4,5,6,7,8,9,10}
776
--
777
--
778
-- Example 2:
779
--
780
-- sequence x, y, z
781
--
782
-- x = {"fred", "barney"}
783
-- y = append(x, "wilma")
784
-- -- y is now {"fred", "barney", "wilma"}
785
--
786
-- z = append(append(y, "betty"), {"bam", "bam"})
787
-- -- z is now {"fred", "barney", "wilma", "betty", {"bam", "bam"}}
788
--
789
--
790
-- See Also:
791
-- [[:prepend]], [[:& -> amp_concat]]
792
793
--****
794
-- Signature:
795
-- function prepend(sequence target, object x)
796
--
797
-- Description:
798
-- Adds an object as the first element of a sequence.
799
--
800
-- Parameters:
801
-- # ##source## : the sequence to add to
802
-- # ##x## : the object to add
803
--
804
-- Returns:
805
-- A **sequence**, whose last elements are those of ##target## and whose
806
-- first element is ##x##.
807
--
808
-- Comments:
809
-- The length of the returned sequence will be ##length(target) + 1## always.
810
--
811
-- If ##x## is an atom this is the same as ##result = x & target##. If ##x## is
812
-- a sequence it is not the same.
813
--
814
-- The case where ##target## itself is prepend()ed to is handled very efficiently.
815
--
816
-- Example 1:
817
--
818
-- prepend({1,2,3}, {0,0}) -- {{0,0}, 1, 2, 3}
819
-- -- Compare with concatenation:
820
-- {0,0} & {1,2,3} -- {0, 0, 1, 2, 3}
821
--
822
--
823
-- Example 2:
824
--
825
-- s = {}
826
-- for i = 1 to 10 do
827
-- s = prepend(s, i)
828
-- end for
829
-- -- s is {10,9,8,7,6,5,4,3,2,1}
830
--
831
--
832
-- See Also:
833
-- [[:append]], [[:& -> amp_concat]]
834
835
836
--****
837
-- Signature:
838
-- function insert(sequence target, object what, integer index)
839
--
840
-- Description:
841
-- Insert an object into a sequence as a new element at a given location.
842
--
843
-- Parameters:
844
-- # ##target## : the sequence to insert into
845
-- # ##what## : the object to insert
846
-- # ##index## : an integer, the position in ##target## where ##what##
847
-- should appear
848
--
849
-- Returns:
850
-- A **sequence**, which is ##target## with one more element at ##index##,
851
-- which is ##what##.
852
--
853
-- Comments:
854
-- ##target## can be a sequence of any shape, and ##what## any kind of object.
855
--
856
-- The length of the returned sequence is ##length(target)+1## always.
857
--
858
-- insert()ing a sequence into a string returns a sequence which is no longer a string.
859
--
860
-- Example 1:
861
--
862
-- s = insert("John Doe", " Middle", 5)
863
-- -- s is {'J','o','h','n'," Middle ",'D','o','e'}
864
--
865
--
866
-- Example 2:
867
--
868
-- s = insert({10,30,40}, 20, 2)
869
-- -- s is {10,20,30,40}
870
--
871
--
872
-- See Also:
873
-- [[:remove]], [[:splice]], [[:append]], [[:prepend]]
874
875
--****
876
-- Signature:
877
-- function splice(sequence target, object what, integer index)
878
--
879
-- Description:
880
-- Inserts an object as a new slice in a sequence at a given position.
881
--
882
-- Parameters:
883
-- # ##target## : the sequence to insert into
884
-- # ##what## : the object to insert
885
-- # ##index## : an integer, the position in ##target## where ##what## should appear
886
--
887
-- Returns:
888
-- A **sequence**, which is ##target## with one or more elements, those of ##what##,
889
-- inserted at locations starting at ##index##.
890
--
891
-- Comments:
892
-- ##target## can be a sequence of any shape, and ##what## any kind of object.
893
--
894
-- The length of this new sequence is the sum of the lengths of ##target## and ##what##
895
-- (atoms are of length 1 for this purpose). ##splice##() is equivalent to
896
-- [[:insert]]() when ##what## is an atom, but not when it is a sequence.
897
--
898
-- Splicing a string into a string results into a new string.
899
--
900
-- Example 1:
901
--
902
-- s = splice("John Doe", " Middle", 5)
903
-- -- s is "John Middle Doe"
904
--
905
--
906
-- Example 2:
907
--
908
-- s = splice({10,30,40}, 20, 2)
909
-- -- s is {10,20,30,40}
910
--
911
--
912
-- See Also:
913
-- [[:insert]], [[:remove]], [[:replace]], [[:& -> amp_concat]]
914
915
--**
916
-- Pad the beginning of a sequence with an object so as to meet a minimum
917
-- length condition.
918
--
919
-- Parameters:
920
-- # ##target## : the sequence to pad.
921
-- # ##size## : an integer, the target minimum size for ##target##
922
-- # ##padding## : an object, usually the character to pad to (defaults to ' ').
923
--
924
-- Returns:
925
-- A **sequence**, either ##target## if it was long enough, or a sequence of
926
-- length ##size## whose last elements are those of ##target## and whose first
927
-- few head elements all equal ##padding##.
928
--
929
-- Comments:
930
-- ##pad_head##() will not remove characters. If ##length(target)## is greater
931
-- than ##size##, this function simply returns ##target##. See [[:head]]()
932
-- if you wish to truncate long sequences.
933
--
934
-- Example 1:
935
--
936
-- s = pad_head("ABC", 6)
937
-- -- s is " ABC"
938
--
939
-- s = pad_head("ABC", 6, '-')
940
-- -- s is "---ABC"
941
--
942
--
943
-- See Also:
944
-- [[:trim_head]], [[:pad_tail]], [[:head]]
945
9464
9474
if size <= length(target) then
9482
return target
949
end if
950
9512
return repeat(ch, size - length(target)) & target
952
end function
953
954
--**
955
-- Pad the end of a sequence with an object so as to meet a minimum length condition.
956
--
957
-- Parameters:
958
-- # ##target## : the sequence to pad.
959
-- # ##size## : an integer, the target minimum size for ##target##
960
-- # ##padding## : an object, usually the character to pad to (defaults to ' ').
961
--
962
-- Returns:
963
-- A **sequence**, either ##target## if it was long enough, or a sequence
964
-- of length ##size## whose first elements are those of ##target## and whose
965
-- last few head elements all equal ##padding##.
966
--
967
-- Comments:
968
-- ##pad_tail##() will not remove characters. If ##length(target)## is greater
969
-- than ##size##, this function simply returns ##target##. See [[:tail]]() if
970
-- you wish to truncate long sequences.
971
--
972
-- Comments:
973
--
974
-- ##pad_tail##() will not remove characters. If ##length(str)## is greater than params, this
975
-- function simply returns str. see tail() if you wish to truncate long sequences.
976
--
977
-- Example 1:
978
--
979
-- s = pad_tail("ABC", 6)
980
-- -- s is "ABC "
981
--
982
-- s = pad_tail("ABC", 6, '-')
983
-- -- s is "ABC---"
984
--
985
--
986
-- See Also:
987
-- [[:trim_tail]], [[:pad_head]], [[:tail]]
988
98951
99051
if size <= length(target) then
9912
return target
992
end if
993
99449
return target & repeat(ch, size - length(target))
995
end function
996
997
--**
998
-- Adds an item to the sequence if its not already there. If it already exists
999
-- in the list, the list is returned unchanged.
1000
--
1001
-- Parameters:
1002
-- # ##needle## : object to add.
1003
-- # ##haystack## : sequence to add it to.
1004
-- # ##order## : an integer; determines how the ##needle## affects the ##haystack##.
1005
-- It can be added to the front (prepended), to the back (appended),
1006
-- or sorted after adding. The default is to prepend it.
1007
--
1008
-- Returns:
1009
-- A **sequence**, which is ##haystack## with ##needle## added to it.
1010
--
1011
-- Comments:
1012
--
1013
-- An error occurs if an invalid ##order## argument is supplied.
1014
--
1015
-- The following enum is provided for specifying ##order##:
1016
-- * ##ADD_PREPEND## ~-- prepend ##needle## to ##haystack##. This is the default option.
1017
-- * ##ADD_APPEND## ~-- append ##needle## to ##haystack##.
1018
-- * ##ADD_SORT_UP## ~-- sort ##haystack## in ascending order after inserting ##needle##
1019
-- * ##ADD_SORT_DOWN## ~-- sort ##haystack## in descending order after inserting ##needle##
1020
--
1021
-- Example 1:
1022
--
1023
-- s = add_item( 1, {3,4,2}, ADD_PREPEND ) -- prepend
1024
-- -- s is {1,3,4,2}
1025
--
1026
--
1027
-- Example 2:
1028
--
1029
-- s = add_item( 1, {3,4,2}, ADD_APPEND ) -- append
1030
-- -- s is {3,4,2,1}
1031
--
1032
--
1033
-- Example 3:
1034
--
1035
-- s = add_item( 1, {3,4,2}, ADD_SORT_UP ) -- ascending
1036
-- -- s is {1,2,3,4}
1037
--
1038
--
1039
-- Example 4:
1040
--
1041
-- s = add_item( 1, {3,4,2}, ADD_SORT_DOWN ) -- descending
1042
-- -- s is {4,3,2,1}
1043
--
1044
--
1045
-- Example 5:
1046
--
1047
-- s = add_item( 1, {3,1,4,2} )
1048
-- -- s is {3,1,4,2} -- Item was already in list so no change.
1049
--
1050
10510
10520
if find(needle, haystack) then
10530
return haystack
1054
end if
10550
switch pOrder do
1056
case ADD_PREPEND then
10570
return prepend(haystack, needle)
1058
1059
case ADD_APPEND then
10600
return append(haystack, needle)
1061
1062
case ADD_SORT_UP then
10630
return sort(append(haystack, needle))
1064
1065
case ADD_SORT_DOWN then
10660
return sort(append(haystack, needle), DESCENDING)
1067
1068
case else
10690
crash("sequence.e:add_item() invalid Order argument '%d'", pOrder)
1070
end switch
1071
10720
return haystack
1073
end function
1074
1075
--**
1076
-- Removes an item from the sequence.
1077
--
1078
-- Parameters:
1079
-- # ##needle## : object to remove.
1080
-- # ##haystack## : sequence to remove it from.
1081
--
1082
-- Returns:
1083
-- A **sequence**, which is ##haystack## with ##needle## removed from it.
1084
--
1085
-- Comments:
1086
-- If ##needle## is not in ##haystack## then ##haystack## is returned unchanged.
1087
--
1088
-- Example 1:
1089
--
1090
-- s = remove_item( 1, {3,4,2,1} ) --> {3,4,2}
1091
-- s = remove_item( 5, {3,4,2,1} ) --> {3,4,2,1}
1092
--
1093
10944
1095
integer lIdx
1096
10974
lIdx = find(needle, haystack)
10984
if not lIdx then
10991
return haystack
1100
end if
1101
11023
if lIdx = 1 then
11031
return haystack[2 .. $]
1104
11052
elsif lIdx = length(haystack) then
11061
return haystack[1 .. $-1]
1107
1108
else
11091
return haystack[1 .. lIdx - 1] & haystack[lIdx + 1 .. $]
1110
end if
1111
end function
1112
1113
--****
1114
-- === Extracting, removing, replacing from/into a sequence
1115
--
1116
1117
--****
1118
-- Signature:
1119
-- function head(sequence source, atom size=1)
1120
--
1121
-- Description:
1122
-- Return the first item(s) of a sequence.
1123
--
1124
-- Parameters:
1125
-- # ##source## : the sequence from which elements will be returned
1126
-- # ##size## : an integer, how many head elements at most will be returned.
1127
-- Defaults to 1.
1128
--
1129
-- Returns:
1130
-- A **sequence**, ##source## if its length is not greater than ##size##,
1131
-- or the ##size## first elements of ##source## otherwise.
1132
--
1133
-- Example 1:
1134
--
1135
-- s2 = head("John Doe", 4)
1136
-- -- s2 is John
1137
--
1138
--
1139
-- Example 2:
1140
--
1141
-- s2 = head("John Doe", 50)
1142
-- -- s2 is John Doe
1143
--
1144
--
1145
-- Example 3:
1146
--
1147
-- s2 = head({1, 5.4, "John", 30}, 3)
1148
-- -- s2 is {1, 5.4, "John"}
1149
--
1150
--
1151
-- See Also:
1152
-- [[:tail]], [[:mid]], [[:slice]]
1153
1154
--****
1155
-- Signature:
1156
-- function tail(sequence source, atom n=length(source) - 1)
1157
--
1158
-- Description:
1159
-- Return the last items of a sequence.
1160
--
1161
-- Parameters:
1162
-- # ##source## : the sequence to get the tail of.
1163
-- # ##size## : an integer, the number of items to return.
1164
-- (defaults to length(source) - 1)
1165
--
1166
-- Returns:
1167
-- A **sequence**, of length at most ##size##. If the length is less than
1168
-- ##size##, then ##source## was returned. Otherwise, the ##size## last elements
1169
-- of ##source## were returned.
1170
--
1171
-- Comments:
1172
-- ##source## can be any type of sequence, including nested sequences.
1173
--
1174
-- Example 1:
1175
--
1176
-- s2 = tail("John Doe", 3)
1177
-- -- s2 is "Doe"
1178
--
1179
--
1180
-- Example 2:
1181
--
1182
-- s2 = tail("John Doe", 50)
1183
-- -- s2 is "John Doe"
1184
--
1185
--
1186
-- Example 3:
1187
--
1188
-- s2 = tail({1, 5.4, "John", 30}, 3)
1189
-- -- s2 is {5.4, "John", 30}
1190
--
1191
--
1192
-- See Also:
1193
-- [[:head]], [[:mid]], [[:slice]]
1194
1195
--**
1196
-- Returns a slice of a sequence, given by a starting point and a length.
1197
--
1198
-- Parameters:
1199
-- # ##source## : the sequence some elements of which will be returned
1200
-- # ##start## : an integer, the lower index of the slice to return
1201
-- # ##len## : an integer, the length of the slice to return
1202
--
1203
-- Returns:
1204
-- A **sequence**, made of at most ##len## elements of ##source##. These
1205
-- elements are at contiguous positions in ##source## starting at ##start##.
1206
--
1207
-- Errors:
1208
-- If ##len## is less than ##-length(source)##, an error occurs.
1209
--
1210
-- Comments:
1211
-- ##len## may be negative, in which case it is added ##length(source)## once.
1212
--
1213
-- Example 1:
1214
--
1215
-- s2 = mid("John Middle Doe", 6, 6)
1216
-- -- s2 is Middle
1217
--
1218
--
1219
-- Example 2:
1220
--
1221
-- s2 = mid("John Middle Doe", 6, 50)
1222
-- -- s2 is Middle Doe
1223
--
1224
--
1225
-- Example 3:
1226
--
1227
-- s2 = mid({1, 5.4, "John", 30}, 2, 2)
1228
-- -- s2 is {5.4, "John"}
1229
--
1230
--
1231
-- See Also:
1232
-- [[:head]], [[:tail]], [[:slice]]
1233
12347
12357
if len<0 then
12361
len += length(source)
12371
if len<0 then
12380
crash("mid(): len was %d and should be greater than %d.",
1239
{len-length(source),-length(source)})
1240
end if
1241
end if
12427
if start > length(source) or len=0 then
12431
return ""
1244
end if
12456
if start<1 then
12461
start=1
1247
end if
12486
if start+len-1 >= length(source) then
12491
return source[start..$]
1250
else
12515
return source[start..len+start-1]
1252
end if
1253
end function
1254
1255
--**
1256
-- Return a portion of the supplied sequence.
1257
--
1258
-- Parameters:
1259
-- # ##source## : the sequence from which to get a portion
1260
-- # ##start## : an integer, the starting point of the portion. Default is 1.
1261
-- # ##stop## : an integer, the ending point of the portion. Default is length(source).
1262
--
1263
-- Returns:
1264
-- A **sequence**.
1265
--
1266
-- Comments:
1267
-- * If the supplied ##start## is less than 1 then it set to 1.
1268
-- * If the supplied ##stop## is less than 1 then ##length(source)## is added to it.
1269
-- In this way, 0 represents the end of ##source##, -1 represents one element
1270
-- in from the end of ##source## and so on.
1271
-- * If the supplied ##stop## is greater than ##length(source)## then it is set to the end.
1272
-- * After these adjustments, and if ##source[start..stop]## makes sense, it is
1273
-- returned, otherwise, ##{}## is returned.
1274
--
1275
-- Examples:
1276
--
1277
-- s2 = slice("John Doe", 6, 8)--> "Doe"
1278
-- s2 = slice("John Doe", 6, 50) --> "Doe"
1279
-- s2 = slice({1, 5.4, "John", 30}, 2, 3) --> {5.4, "John"}
1280
-- s2 = slice({1,2,3,4,5}, 2, -1) --> {2,3,4}
1281
-- s2 = slice({1,2,3,4,5}, 2) --> {2,3,4,5}
1282
-- s2 = slice({1,2,3,4,5}, , 4) --> {1,2,3,4}
1283
--
1284
--
1285
-- See Also:
1286
-- [[:head]], [[:mid]], [[:tail]]
1287
128810
1289
129010
if stop < 1 then
12914
stop += length(source)
1292
12936
elsif stop > length(source) then
12941
stop = length(source)
1295
1296
end if
1297
129810
if start < 1 then
12991
start = 1
1300
end if
1301
130210
if start > stop then
13031
return ""
1304
end if
1305
13069
return source[start..stop]
1307
end function
1308
1309
--**
1310
-- Perform a vertical slice on a nested sequence
1311
--
1312
-- Parameters:
1313
-- # ##source## : the sequence to take a vertical slice from
1314
-- # ##colno## : an atom, the column number to extract (rounded down)
1315
-- # ##error_control## : an object which says what to do if some element
1316
-- does not exist. Defaults to 0 (crash in such a circumstance).
1317
--
1318
-- Returns:
1319
-- A **sequence**, usually of the same length as ##source##, made of all
1320
-- the ##source[x][colno]##.
1321
--
1322
-- Errors:
1323
-- If an element is not defined and ##error_control## is 0, an error occurs.
1324
-- If ##colno## is less than 1, it cannot be any valid column, and an error occurs.
1325
--
1326
-- Comments:
1327
-- If it is not possible to return the sequence of all ##source[x][colno]]##
1328
-- for all available ##x##, the outcome is decided by ##error_control##:
1329
-- * If 0 (the default), program is aborted.
1330
-- * If a nonzero atom, the short vertical slice is returned.
1331
-- * Otherwise, elements of ##error_control## will be taken to make for any
1332
-- missing element. A short vertical slice is returned if ##error_control## is
1333
-- exhausted.
1334
--
1335
-- Example 1:
1336
--
1337
-- s = vslice({{5,1}, {5,2}, {5,3}}, 2)
1338
-- -- s is {1,2,3}
1339
--
1340
-- s = vslice({{5,1}, {5,2}, {5,3}}, 1)
1341
-- -- s is {5,5,5}
1342
--
1343
--
1344
-- See Also:
1345
-- [[:slice]], [[:project]]
1346
13475
1348
sequence ret
1349
integer substitutes, current_sub
1350
13515
if colno < 1 then
13520
crash("sequence:vslice(): colno should be a valid index, but was %d",colno)
1353
end if
1354
13555
ret = source
13565
if atom(error_control) then
13573
substitutes =-(not error_control)
1358
else
13592
substitutes = length(error_control)
13602
current_sub = 1
1361
end if
1362
13635
for i = 1 to length(source) do
136414
if colno >= 1+length(source[i]) then
13652
if substitutes=-1 then
13660
crash("sequence:vslice(): colno should be a valid index on the %d-th element, but was %d", {i,colno})
13672
elsif substitutes=0 then
13681
return ret[1..i-1]
1369
else
13701
substitutes -= 1
13711
ret[i] = error_control[current_sub]
13721
current_sub += 1
1373
end if
1374
else
137512
ret[i] = source[i][colno]
1376
end if
137713
end for
1378
13794
return ret
1380
end function
1381
1382
--****
1383
-- Signature:
1384
-- function remove(sequence target, atom start, atom stop=start)
1385
--
1386
-- Description:
1387
-- Remove an item, or a range of items from a sequence.
1388
--
1389
-- Parameters:
1390
-- # ##target## : the sequence to remove from.
1391
-- # ##start## : an atom, the (starting) index at which to remove
1392
-- # ##stop## : an atom, the index at which to stop removing (defaults to ##start##)
1393
--
1394
-- Returns:
1395
-- A **sequence**, obtained from ##target## by carving the ##start..stop## slice
1396
-- out of it.
1397
--
1398
-- Comments:
1399
-- A new sequence is created. ##target## can be a string or complex sequence.
1400
--
1401
-- Example 1:
1402
--
1403
-- s = remove("Johnn Doe", 4)
1404
-- -- s is "John Doe"
1405
--
1406
--
1407
-- Example 2:
1408
--
1409
-- s = remove({1,2,3,3,4}, 4)
1410
-- -- s is {1,2,3,4}
1411
--
1412
--
1413
-- Example 3:
1414
--
1415
-- s = remove("John Middle Doe", 6, 12)
1416
-- -- s is "John Doe"
1417
--
1418
--
1419
-- Example 4:
1420
--
1421
-- s = remove({1,2,3,3,4,4}, 4, 5)
1422
-- -- s is {1,2,3,4}
1423
--
1424
--
1425
-- See Also:
1426
-- [[:replace]], [[:insert]], [[:splice]], [[:remove_all]]
1427
1428
1429
--**
1430
-- Changes a sequence slice, possibly with padding
1431
--
1432
-- Parameters:
1433
-- # ##target## : a sequence, a modified copy of which will be returned
1434
-- # ##source## : a sequence, to be patched inside or outside ##target##
1435
-- # ##start## : an integer, the position at which to patch
1436
-- # ##filler## : an object, used for filling gaps. Defaults to ' '
1437
--
1438
-- Returns:
1439
-- A **sequence**, which looks like ##target##, but a slice starting at ##start##
1440
-- equals ##source##.
1441
--
1442
-- Comments:
1443
--
1444
-- In some cases, this call will result in the same result as [[:replace]]().
1445
--
1446
-- If ##source## doesn't fit into ##target## because of the lengths and the
1447
-- supplied ##start## value, gaps will be created, and ##filler## is used to
1448
-- fill them in.
1449
--
1450
-- Notionally, ##target## has an infinite amount of ##filler## on both sides,
1451
-- and ##start## counts position relative to where ##target## actually starts.
1452
-- Then, notionally, a [[:replace]]() operation is performed.
1453
--
1454
-- Example 1:
1455
--
1456
-- sequence source = "abc", target = "John Doe"
1457
-- sequence s = patch(target, source, 11,'0')
1458
-- -- s is now "John Doe00abc"
1459
--
1460
--
1461
-- Example 2:
1462
--
1463
-- sequence source = "abc", target = "John Doe"
1464
-- sequence s = patch(target, source, -1)
1465
-- -- s is now "abcohn Doe"
1466
-- Note that there was no gap to fill.
1467
-- Since -1 = 1 - 2, the patching started 2 positions before the initial 'J'.
1468
--
1469
--
1470
-- Example 3:
1471
--
1472
-- sequence source = "abc", target = "John Doe"
1473
-- sequence s = patch(target, source, 6)
1474
-- -- s is now "John Dabc"
1475
--
1476
--
1477
-- See Also:
1478
-- [[:mid]], [[:replace]]
1479
14805
14815
if start + length(source) <= 0 then
14820
return source & repeat(filler, -start-length(source))+1 & target
14835
elsif start + length(source) <= length(target) then
14842
if start<=0 then
14851
return source & target[start+length(source)..$]
1486
else
14871
return target[1..start-1] & source & target[start+length(source)..$]
1488
end if
14893
elsif start <= 1 then
14901
return source
14912
elsif start <= length(target)+1 then
14921
return target[1..start-1] & source
1493
else
14941
return target & repeat(filler,start-length(target)-1) & source
1495
end if
1496
end function
1497
1498
--**
1499
-- Removes all occurrences of some object from a sequence.
1500
--
1501
-- Parameters:
1502
-- # ##needle## : the object to remove.
1503
-- # ##haystack## : the sequence to remove from.
1504
--
1505
-- Returns:
1506
-- A **sequence**, of length at most ##length(haystack)##, and which has
1507
-- the same elements, without any copy of ##needle## left
1508
--
1509
-- Comments:
1510
-- This function weeds elements out, not sub-sequences.
1511
--
1512
-- Example 1:
1513
--
1514
-- s = remove_all( 1, {1,2,4,1,3,2,4,1,2,3} )
1515
-- -- s is {2,4,3,2,4,2,3}
1516
--
1517
--
1518
-- Example 2:
1519
--
1520
-- s = remove_all('x', "I'm toox secxksy for my shixrt.")
1521
-- -- s is "I'm too secksy for my shirt."
1522
--
1523
--
1524
-- See Also:
1525
-- [[:remove]], [[:replace]]
1526
15275
1528
integer ts, te, ss, se
1529
1530
-- See if we have to do anything at all.
15315
se = find(needle, haystack)
15325
if se = 0 then
15332
return haystack
1534
end if
1535
1536
-- Now we know there is at least one occurrence and because
1537
-- it's the first one, we don't have to move anything yet.
1538
-- So pretend we have and set up the 'end' variables
1539
-- as if we had moved stuff.
15403
se -= 1
15413
te = se
1542
15433
while se > 0 with entry do
1544
-- Shift elements down the sequence.
154510
haystack[ts .. te] = haystack[ss .. se]
1546
1547
entry
1548
-- Calc where the next target start is (1 after the previous end)
154913
ts = te + 1
1550
1551
-- Calc where to start the next search (2 after the previous end)
155213
ss = se + 2
1553
1554
-- See if we got another one.
155513
se = find_from(needle, haystack, ss)
1556
1557
-- We have another one, so calculate the source end(1 before the needle)
155813
se = se - 1
1559
1560
-- Calc the target end (start + length of what we are moving)
156113
te = ts + se - ss
156213
end while
1563
1564
-- Check to see if there is anything after the final needle
1565
-- and move it.
15663
if ss <= length(haystack) then
15671
te = ts + length(haystack) - ss
15681
haystack[ts .. te] = haystack[ss .. $]
1569
else
1570
-- Need to backtrack one needle.
15712
te = ts - 1
1572
end if
1573
1574
-- Return only the stuff we moved.
15753
return haystack[1 .. te]
1576
end function
1577
1578
--**
1579
-- Keeps all occurrences of a set of objects from a sequence and removes all others.
1580
--
1581
-- Parameters:
1582
-- # ##needles## : the set of objects to retain.
1583
-- # ##haystack## : the sequence to remove items not in ##needles##.
1584
--
1585
-- Returns:
1586
-- A **sequence** containing only those objects from ##haystack## that are also in ##needles##.
1587
--
1588
-- Example:
1589
--
1590
-- s = retain_all( {1,3,5}, {1,2,4,1,3,2,4,1,2,3} ) --> {1,1,3,1,3}
1591
-- s = retain_all("0123456789", "+34 (04) 555-44392") -> "340455544392"
1592
--
1593
--
1594
-- See Also:
1595
-- [[:remove]], [[:replace]], [[:remove_all]]
1596
15975
1598
integer lp
1599
integer np
1600
sequence result
1601
16025
if atom(needles) then
16031
needles = {needles}
1604
end if
16055
if length(needles) = 0 then
16061
return {}
1607
end if
16084
if length(haystack) = 0 then
16091
return {}
1610
end if
1611
16123
result = haystack
16133
lp = length(haystack)
16143
np = 1
16153
for i = 1 to length(haystack) do
161630
if find(haystack[i], needles) then
161715
if np < i then
16184
result[np .. lp] = haystack[i..$]
1619
end if
162015
np += 1
1621
else
162215
lp -= 1
1623
end if
162430
end for
1625
16263
return result[1 .. lp]
1627
1628
end function
1629
1630
--**
1631
-- Filter a sequence based on a user supplied comparator function.
1632
--
1633
-- Parameters:
1634
-- * ##source## : sequence to filter
1635
-- * ##rid## : Either a [[:routine_id]] of function to use as comparator or one
1636
-- of the predefined comparitors.
1637
-- * ##userdata## : an object passed to each invocation of ##rid##. If omitted,
1638
-- {} is used.
1639
-- * ##rangetype##: A sequence. Only used when ##rid## is "in" or "out". This is
1640
-- used to let the function know how to interpret ##userdata##. When ##rangetype##
1641
-- is an empty string (which is the default), then ##userdata## is treated as a set of zero or more
1642
-- discrete items such that "in" will only return items from ##source## that are
1643
-- in the set of item in ##userdata## and "out" returns those not in ##userdata##.
1644
-- The other values for ##rangetype## mean that ##userdata## must be a set of
1645
-- exactly two items, that represent the lower and upper limits of a range of
1646
-- values.
1647
--
1648
-- Returns:
1649
-- A **sequence**, made of the elements in ##source## which passed the
1650
-- comparitor test.
1651
--
1652
-- Comments:
1653
-- * The only items from ##source## that are returned are those that pass the test.
1654
-- * When ##rid## is a routine_id, that user defined routine must be a function.
1655
-- Each item in ##source##, along with the ##userdata## is passed to the function.
1656
-- The function must return a non-zero atom if the item is to be included in the
1657
-- result sequence, otherwise it should return zero to exclude it from the result.
1658
-- * The predefined comparitors are...
1659
--
1660
-- | "<" or "lt" | return items in ##source## that are less than ##userdata## |
1661
-- | "<=" or "le" | return items in ##source## that are less than or equal to ##userdata## |
1662
-- | "=" or "==" or "eq" | return items in ##source## that are equal to ##userdata## |
1663
-- | "!=" or "ne" | return items in ##source## that are not equal to ##userdata## |
1664
-- | ">" or "gt" | return items in ##source## that are greater than ##userdata## |
1665
-- | ">=" or "ge" | return items in ##source## that are greater than or equal to ##userdata## |
1666
-- | "in" | return items in ##source## that are in ##userdata## |
1667
-- | "out" | return items in ##source## that are not in ##userdata## |
1668
--
1669
-- * Range Type Usage
1670
-- |= Range Type |= Meaning |
1671
-- | "[]" | Inclusive range. Lower and upper are in the range. |
1672
-- | "[)" | Low Inclusive range. Lower is in the range but upper is not. |
1673
-- | "(]" | High Inclusive range. Lower is not in the range but upper is. |
1674
-- | "()" | Exclusive range. Lower and upper are not in the range. |
1675
--
1676
-- Example 1:
1677
--
1678
-- function mask_nums(atom a, object t)
1679
-- if sequence(t) then
1680
-- return 0
1681
-- end if
1682
-- return and_bits(a, t) != 0
1683
-- end function
1684
--
1685
-- function even_nums(atom a, atom t)
1686
-- return and_bits(a,1) = 0
1687
-- end function
1688
--
1689
-- constant data = {5,8,20,19,3,2,10}
1690
-- filter(data, routine_id("mask_nums"), 1) --> {5,19,3}
1691
-- filter(data, routine_id("mask_nums"), 2) -->{19, 3, 2, 10}
1692
-- filter(data, routine_id("even_nums")) -->{8, 20, 2, 10}
1693
--
1694
-- -- Using 'in' and 'out' with sets.
1695
-- filter(data, "in", {3,4,5,6,7,8}) -->{5,8,3}
1696
-- filter(data, "out", {3,4,5,6,7,8}) -->{20,19,2,10}
1697
--
1698
-- -- Using 'in' and 'out' with ranges.
1699
-- filter(data, "in", {3,8}, "[]") --> {5,8,3}
1700
-- filter(data, "in", {3,8}, "[)") --> {5,3}
1701
-- filter(data, "in", {3,8}, "(]") --> {5,8}
1702
-- filter(data, "in", {3,8}, "()") --> {5}
1703
-- filter(data, "out", {3,8}, "[]") --> {20,19,2,10}
1704
-- filter(data, "out", {3,8}, "[)") --> {8,20,19,2,10}
1705
-- filter(data, "out", {3,8}, "(]") --> {20,19,3,2,10}
1706
-- filter(data, "out", {3,8}, "()") --> {8,20,19,3,2,10}
1707
--
1708
--
1709
-- Example 3:
1710
--
1711
-- function quiksort(sequence s)
1712
-- if length(s) < 2 then
1713
-- return s
1714
-- end if
1715
-- return quiksort( filter(s[2..$], "<=", s[1]) ) & s[1] & quiksort(filter(s[2..$], ">", s[1]))
1716
-- end function
1717
-- ? quiksort( {5,4,7,2,4,9,1,0,4,32,7,54,2,5,8,445,67} )
1718
-- --> {0,1,2,2,4,4,4,5,5,7,7,8,9,32,54,67,445}
1719
--
1720
--
1721
-- See Also:
1722
-- [[:apply]]
1723
172450
1725
sequence dest
1726
integer idx
1727
172850
if length(source) = 0 then
17291
return source
1730
end if
173149
dest = repeat(0, length(source))
173249
idx = 0
173349
switch rid do
1734
case "<", "lt" then
17352
for a = 1 to length(source) do
173614
if compare(source[a], userdata) < 0 then
17376
idx += 1
17386
dest[idx] = source[a]
1739
end if
174014
end for
1741
1742
case "<=", "le" then
174312
for a = 1 to length(source) do
174463
if compare(source[a], userdata) <= 0 then
174530
idx += 1
174630
dest[idx] = source[a]
1747
end if
174863
end for
1749
1750
case "=", "==", "eq" then
17513
for a = 1 to length(source) do
175221
if compare(source[a], userdata) = 0 then
17533
idx += 1
17543
dest[idx] = source[a]
1755
end if
175621
end for
1757
1758
case "!=", "ne" then
17592
for a = 1 to length(source) do
176014
if compare(source[a], userdata) != 0 then
176112
idx += 1
176212
dest[idx] = source[a]
1763
end if
176414
end for
1765
1766
case ">", "gt" then
176712
for a = 1 to length(source) do
176863
if compare(source[a], userdata) > 0 then
176933
idx += 1
177033
dest[idx] = source[a]
1771
end if
177263
end for
1773
1774
case ">=", "ge" then
17752
for a = 1 to length(source) do
177614
if compare(source[a], userdata) >= 0 then
17778
idx += 1
17788
dest[idx] = source[a]
1779
end if
178014
end for
1781
1782
case "in" then
17836
switch rangetype do
1784
case "" then
17852
for a = 1 to length(source) do
178614
if find(source[a], userdata) then
17876
idx += 1
17886
dest[idx] = source[a]
1789
end if
179014
end for
1791
1792
case "[]" then
17931
for a = 1 to length(source) do
17947
if compare(source[a], userdata[1]) >= 0 then
17956
if compare(source[a], userdata[2]) <= 0 then
17963
idx += 1
17973
dest[idx] = source[a]
1798
end if
1799
end if
18007
end for
1801
1802
case "[)" then
18031
for a = 1 to length(source) do
18047
if compare(source[a], userdata[1]) >= 0 then
18056
if compare(source[a], userdata[2]) < 0 then
18062
idx += 1
18072
dest[idx] = source[a]
1808
end if
1809
end if
18107
end for
1811
case "(]" then
18121
for a = 1 to length(source) do
18137
if compare(source[a], userdata[1]) > 0 then
18145
if compare(source[a], userdata[2]) <= 0 then
18152
idx += 1
18162
dest[idx] = source[a]
1817
end if
1818
end if
18197
end for
1820
case "()" then
18211
for a = 1 to length(source) do
18227
if compare(source[a], userdata[1]) > 0 then
18235
if compare(source[a], userdata[2]) < 0 then
18241
idx += 1
18251
dest[idx] = source[a]
1826
end if
1827
end if
18287
end for
1829
1830
end switch
1831
1832
case "out" then
18336
switch rangetype do
1834
case "" then
18352
for a = 1 to length(source) do
183614
if not find(source[a], userdata) then
18378
idx += 1
18388
dest[idx] = source[a]
1839
end if
184014
end for
1841
1842
case "[]" then
18431
for a = 1 to length(source) do
18447
if compare(source[a], userdata[1]) < 0 then
18451
idx += 1
18461
dest[idx] = source[a]
18476
elsif compare(source[a], userdata[2]) > 0 then
18483
idx += 1
18493
dest[idx] = source[a]
1850
end if
18517
end for
1852
1853
case "[)" then
18541
for a = 1 to length(source) do
18557
if compare(source[a], userdata[1]) < 0 then
18561
idx += 1
18571
dest[idx] = source[a]
18586
elsif compare(source[a], userdata[2]) >= 0 then
18594
idx += 1
18604
dest[idx] = source[a]
1861
end if
18627
end for
1863
case "(]" then
18641
for a = 1 to length(source) do
18657
if compare(source[a], userdata[1]) <= 0 then
18662
idx += 1
18672
dest[idx] = source[a]
18685
elsif compare(source[a], userdata[2]) > 0 then
18693
idx += 1
18703
dest[idx] = source[a]
1871
end if
18727
end for
1873
case "()" then
18741
for a = 1 to length(source) do
18757
if compare(source[a], userdata[1]) <= 0 then
18762
idx += 1
18772
dest[idx] = source[a]
18785
elsif compare(source[a], userdata[2]) >= 0 then
18794
idx += 1
18804
dest[idx] = source[a]
1881
end if
18827
end for
1883
1884
end switch
1885
1886
case else
18874
for a = 1 to length(source) do
188830
if call_func(rid, {source[a], userdata}) then
188914
idx += 1
189014
dest[idx] = source[a]
1891
end if
189230
end for
1893
end switch
189449
return dest[1..idx]
1895
end function
1896
18979
18989
return t_alpha(elem)
1899
end function
1900
1901
--**
1902
-- Signature:
1903
-- public constant STDFLTR_ALPHA
1904
--
1905
-- Description:
1906
-- Predefined routine_id for use with [[:filter]]().
1907
--
1908
-- Comments:
1909
-- Used to filter out non-alphabetic characters from a string.
1910
--
1911
-- Example:
1912
--
1913
-- -- Collect only the alphabetic characters from 'text'
1914
-- result = filter(text, STDFLTR_ALPHA)
1915
--
1916
--
1917
1918101
public constant STDFLTR_ALPHA = routine_id("filter_alpha")
1919
1920
--****
1921
-- Signature:
1922
-- function replace(sequence target, object replacement, integer start, integer stop=start)
1923
--
1924
-- Description:
1925
-- Replace a slice in a sequence by an object.
1926
--
1927
-- Parameters:
1928
-- # ##target## : the sequence in which replacement will be done.
1929
-- # ##replacement## : an object, the item to replace with.
1930
-- # ##start## : an integer, the starting index of the slice to replace.
1931
-- # ##stop## : an integer, the stopping index of the slice to replace.
1932
--
1933
-- Returns:
1934
-- A **sequence**, which is made of ##target## with the ##start..stop## slice
1935
-- removed and replaced by ##replacement##, which is [[:splice]]()d in.
1936
--
1937
-- Comments:
1938
-- * A new sequence is created. ##target## can be a string or complex sequence
1939
-- of any shape.
1940
--
1941
-- * To replace by just one element, enclose ##replacement## in curly braces,
1942
-- which will be removed at replace time.
1943
--
1944
-- Example 1:
1945
--
1946
-- s = replace("John Middle Doe", "Smith", 6, 11)
1947
-- -- s is "John Smith Doe"
1948
--
1949
-- s = replace({45.3, "John", 5, {10, 20}}, 25, 2, 3)
1950
-- -- s is {45.3, 25, {10, 20}}
1951
--
1952
--
1953
-- See Also:
1954
-- [[:splice]], [[:remove]], [[:remove_all]]
1955
1956
--**
1957
-- Description:
1958
-- Replaces all occurrences of ##olddata## with ##newdata##
1959
--
1960
-- Parameters:
1961
-- # ##source## : the sequence in which replacements will be done.
1962
-- # ##olddata## : the sequence/item which is going to be replaced. If this
1963
-- is an empty sequence, the ##source## is returned as is.
1964
-- # ##newdata## : the sequence/item which will be the replacement.
1965
--
1966
-- Returns:
1967
-- A **sequence**, which is made of ##source## with all ##olddata## occurrences
1968
-- replaced by ##newdata##.
1969
--
1970
-- Comments:
1971
-- This also removes all ##olddata## occurrences when ##newdata## is "".
1972
--
1973
-- Example:
1974
--
1975
-- s = replace_all("abracadabra", 'a', 'X')
1976
-- -- s is now "XbrXcXdXbrX"
1977
-- s = replace_all("abracadabra", "ra", 'X')
1978
-- -- s is now "abXcadabX"
1979
-- s = replace_all("abracadabra", "a", "aa")
1980
-- -- s is now "aabraacaadaabraa"
1981
-- s = replace_all("abracadabra", "a", "")
1982
-- -- s is now "brcdbr"
1983
--
1984
--
1985
-- See Also:
1986
-- [[:replace]], [[:remove_all]]
1987
198849
1989
integer startpos
1990
integer endpos
1991
199249
if atom(olddata) then
19932
olddata = {olddata}
1994
end if
1995
199649
if atom(newdata) then
19972
newdata = {newdata}
1998
end if
1999
200049
if length(olddata) = 0 then
20011
return source
2002
end if
2003
200448
endpos = 1
200548
while startpos != 0 with entry do
200697
endpos = startpos + length(olddata) - 1
200797
source = replace(source, newdata, startpos, endpos)
200897
endpos = startpos + length(newdata)
2009
entry
2010145
startpos = match_from(olddata, source, endpos)
2011145
end while
2012
201348
return source
2014
end function
2015
2016
--**
2017
-- Turns a sequences of indexes into the sequence of elements in a source that have such indexes.
2018
--
2019
-- Parameters:
2020
-- # ##source## : the sequence from which to extract elements
2021
-- # ##indexes## : a sequence of atoms, the indexes of the elements to be fetched in ##source##.
2022
--
2023
-- Returns:
2024
-- A **sequence**, of length at most ##length(indexes)##. If ##p## is the r-th element of ##indexes## which is valid on ##source##, then ##result[r]## is ##source[p]##.
2025
--
2026
-- Example 1:
2027
--
2028
-- s = extract({11,13,15,17},{3,1,2,1,4})
2029
-- -- s is {15,11,13,11,17}
2030
--
2031
--
2032
-- See Also:
2033
-- [[:slice]]
2034
203522
2036
object p
2037
203822
for i = 1 to length(indexes) do
203948
p = indexes[i]
204048
if not valid_index(source,p) then
20410
crash("%d is not a valid index on the input sequence",p)
2042
end if
204348
indexes[i] = source[p]
204448
end for
204522
return indexes
2046
end function
2047
2048
--**
2049
-- Creates a list of sequences based on selected elements from sequences in the source.
2050
--
2051
-- Parameters:
2052
-- # ##source## : a list of sequences.
2053
-- # ##coords## : a list of index lists.
2054
--
2055
-- Returns:
2056
-- A **sequence**, with the same length as ##source##. Each of its elements is a sequence,
2057
-- the length of ##coords##. Each innermost sequence is made of the
2058
-- elements from the corresponding source sub-sequence.
2059
--
2060
-- Comments:
2061
-- For each sequence in ##source##, a set of sub-sequences is created; one for
2062
-- each index list in ##coords##. An index list is just a sequence containing
2063
-- indexes for items in a sequence.
2064
--
2065
-- Example 1:
2066
--
2067
-- s = project({ "ABCD", "789"}, {{1,2}, {3,1}, {2}})
2068
-- -- s is {{"AB","CA","B"},{"78","97","8"}}
2069
--
2070
--
2071
-- See Also:
2072
-- [[:vslice]], [[:extract]]
2073
20742
2075
sequence result
2076
20772
result = repeat( repeat(0, length(coords)), length(source) )
20782
for i = 1 to length(source) do
20797
for j = 1 to length(coords) do
208018
result[i][j] = extract(source[i], coords[j])
208118
end for
20827
end for
20832
return result
2084
end function
2085
2086
--****
2087
-- === Changing the shape of a sequence
2088
--
2089
2090
--**
2091
-- Split a sequence on separator delimiters into a number of sub-sequences.
2092
--
2093
-- Parameters:
2094
-- # ##delim## : an object (default is ' '). The delimiter that separates items
2095
-- in ##source##.
2096
-- # ##source## : the sequence to split.
2097
-- # ##limit## : an integer (default is 0). The maximum number of sub-sequences
2098
-- to create. If zero, there is no limit.
2099
-- # ##no_empty## : an integer (default is 0). If not zero then all zero-length sub-sequences
2100
-- are removed from the returned sequence. Use this when leading,
2101
-- trailing and duplicated delimiters are not significant.
2102
--
2103
-- Returns:
2104
-- A **sequence**, of sub-sequences of ##source##. Delimiters are removed.
2105
--
2106
-- Comments:
2107
-- This function may be applied to a string sequence or a complex sequence.
2108
--
2109
-- If ##limit## is > 0, this is the maximum number of sub-sequences that will
2110
-- created, otherwise there is no limit.
2111
--
2112
-- Example 1:
2113
--
2114
-- result = split(,"John Middle Doe")
2115
-- -- result is {"John", "Middle", "Doe"}
2116
--
2117
--
2118
-- Example 2:
2119
--
2120
-- result = split(",", "John,Middle,Doe", 2)
2121
-- -- result is {"John", "Middle,Doe"}
2122
--
2123
--
2124
-- See Also:
2125
-- [[:split_any]], [[:breakup]], [[:join]]
2126
212725
212825
sequence ret = {}
2129
integer start
2130
integer pos
2131
213225
if length(st) = 0 then
21331
return ret
2134
end if
2135
2136
213724
if sequence(delim) then
2138
-- Handle the simple case of split("", "123"), opposite is join({"1","2","3"}, "") -- "123"
21394
if equal(delim, "") then
21402
for i = 1 to length(st) do
21414
st[i] = {st[i]}
21424
limit -= 1
21434
if limit = 0 then
21441
st = append(st[1 .. i],st[i+1 .. $])
21451
exit
2146
end if
21473
end for
2148
21492
return st
2150
end if
2151
21522
start = 1
21532
while start <= length(st) do
21545
pos = match_from(delim, st, start)
2155
21565
if pos = 0 then
21571
exit
2158
end if
2159
21604
ret = append(ret, st[start..pos-1])
21614
start = pos+length(delim)
21624
limit -= 1
21634
if limit = 0 then
21640
exit
2165
end if
21664
end while
2167
else
216820
start = 1
216920
while start <= length(st) do
217071
pos = find_from(delim, st, start)
2171
217271
if pos = 0 then
217316
exit
2174
end if
2175
217655
ret = append(ret, st[start..pos-1])
217755
start = pos + 1
217855
limit -= 1
217955
if limit = 0 then
21801
exit
2181
end if
218254
end while
2183
end if
2184
218522
ret = append(ret, st[start..$])
2186
218722
integer k = length(ret)
218822
if no_empty then
21892
k = 0
21902
for i = 1 to length(ret) do
219110
if length(ret[i]) != 0 then
21925
k += 1
21935
if k != i then
21943
ret[k] = ret[i]
2195
end if
2196
end if
219710
end for
2198
end if
2199
220022
if k < length(ret) then
22011
return ret[1 .. k]
2202
else
220321
return ret
2204
end if
2205
end function
2206
2207
--**
2208
-- Split a sequence by any of the separators in the list of delimiters.
2209
--
2210
-- If limit is > 0 then limit the number of tokens that will be split to limit.
2211
--
2212
-- Parameters:
2213
-- # ##source## : the sequence to split.
2214
-- # ##delim## : a list of delimiters to split by.
2215
-- # ##limit## : an integer (default is 0). The maximum number of sub-sequences
2216
-- to create. If zero, there is no limit.
2217
-- # ##no_empty## : an integer (default is 0). If not zero then all zero-length sub-sequences
2218
-- removed from the returned sequence. Use this when leading,
2219
-- trailing and duplicated delimiters are not significant.
2220
--
2221
-- Comments:
2222
-- This function may be applied to a string sequence or a complex sequence.
2223
--
2224
-- It works like ##split##(), but in this case ##delim## is a set of potential
2225
-- delimiters rather than a single delimiter.
2226
--
2227
-- Example 1:
2228
--
2229
-- result = split_any("One,Two|Three.Four", ".,|")
2230
-- -- result is {"One", "Two", "Three", "Four"}
2231
-- result = split_any(",One,,Two|.Three||.Four,", ".,|",,1) -- No Empty option
2232
-- -- result is {"One", "Two", "Three", "Four"}
2233
--
2234
--
2235
-- See Also:
2236
-- [[:split]], [[:breakup]], [[:join]]
2237
22384
22394
sequence ret = {}
22404
integer start = 1, pos, next_pos
2241
22424
if atom(delim) then
22431
delim = {delim}
2244
end if
2245
22464
if length(delim) = 0 then
22470
crash("sequence:split_any(): delimiter length must be greater than 0")
2248
end if
2249
22504
while 1 do
225115
pos = find_any(delim, source, start)
225215
next_pos = pos + 1
225315
if pos then
225412
ret = append(ret, source[start..pos-1])
225512
start = next_pos
225612
limit -= 1
225712
if limit = 0 then
22581
exit
2259
end if
2260
else
22613
exit
2262
end if
226311
end while
2264
22654
ret = append(ret, source[start..$])
2266
22674
integer k = length(ret)
22684
if no_empty then
22691
k = 0
22701
for i = 1 to length(ret) do
22718
if length(ret[i]) != 0 then
22723
k += 1
22733
if k != i then
22743
ret[k] = ret[i]
2275
end if
2276
end if
22778
end for
2278
end if
2279
22804
if k < length(ret) then
22811
return ret[1 .. k]
2282
else
22833
return ret
2284
end if
2285
end function
2286
2287
--**
2288
-- Join sequences together using a delimiter.
2289
--
2290
-- Parameters:
2291
-- # ##items## : the sequence of items to join.
2292
-- # ##delim## : an object, the delimiter to join by. Defaults to " ".
2293
--
2294
-- Comments:
2295
-- This function may be applied to a string sequence or a complex sequence
2296
--
2297
-- Example 1:
2298
--
2299
-- result = join({"John", "Middle", "Doe"})
2300
-- -- result is "John Middle Doe"
2301
--
2302
--
2303
-- Example 2:
2304
--
2305
-- result = join({"John", "Middle", "Doe"}, ",")
2306
-- -- result is "John,Middle,Doe"
2307
--
2308
--
2309
-- See Also:
2310
-- [[:split]], [[:split_any]], [[:breakup]]
2311
23125
2313
object ret
2314
23155
if not length(items) then return {} end if
2316
23175
ret = {}
23185
for i=1 to length(items)-1 do
23199
ret &= items[i] & delim
23209
end for
2321
23225
ret &= items[$]
2323
23245
return ret
2325
end function
2326
2327
-- Style options for breakup()
2328
2329
public enum
2330
--** Indicates that ##size## parameter is maximum length of sub-sequence. See [[:breakup]]
2331101
BK_LEN,
2332
--** Indicates that ##size## parameter is maximum number of sub-sequence. See [[:breakup]]
2333101
BK_PIECES
2334
2335
--**
2336
-- Breaks up a sequence into multiple sequences of a given length.
2337
--
2338
-- Parameters:
2339
-- # ##source## : the sequence to be broken up into sub-sequences.
2340
-- # ##size## : an object, if an integer it is either the maximum length of
2341
-- each resulting sub-sequence or the maximum number of
2342
-- sub-sequences to break ##source## into. \\
2343
-- If ##size## is a sequence, it is a list of element counts
2344
-- for the sub-sequences it creates.
2345
-- # ##style## : an integer, Either BK_LEN if ##size## integer represents
2346
-- the sub-sequences' maximum length, or BK_PIECES if
2347
-- the ##size## integer represents the maximum number of
2348
-- sub-sequences (pieces) to break ##source## into.
2349
--
2350
-- Returns:
2351
-- A **sequence**, of sequences.
2352
--
2353
-- Comments:
2354
-- **When ##size## is an integer and ##style## is BK_LEN...**\\
2355
-- The sub-sequences have length ##size##, except possibly the last one,
2356
-- which may be shorter. For example if ##source## has 11 items and ##size## is
2357
-- 3, then the first three sub-sequences will get 3 items each and the remaining
2358
-- 2 items will go into the last sub-sequence. If ##size## is less than 1 or
2359
-- greater than the length of the ##source##, the ##source## is returned as the
2360
-- only sub-sequence.
2361
--
2362
-- **When ##size## is an integer and ##style## is BK_PIECES...**\\
2363
-- There is exactly ##size## sub-sequences created. If the ##source## is not
2364
-- evenly divisible into that many pieces, then the lefthand sub-sequences will
2365
-- contain one more element than the right-hand sub-sequences. For example, if
2366
-- source contains 10 items and we break it into 3 pieces, piece #1 gets 4 elements,
2367
-- piece #2 gets 3 items and piece #3 gets 3 items - a total of 10. If source had
2368
-- 11 elements then the pieces will have 4,4, and 3 respectively.
2369
--
2370
-- **When ##size## is a sequence...**\\
2371
-- The style parameter is ignored in this case. The source will be broken up
2372
-- according to the counts contained in the size parameter. For example, if
2373
-- ##size## was {3,4,0,1} then piece #1 gets 3 items, #2 gets 4 items, #3 gets
2374
-- 0 items, and #4 gets 1 item. Note that if not all items from source are
2375
-- placed into the sub-sequences defined by ##size##, and //extra// sub-sequence
2376
-- is appended that contains the remaining items from ##source##.
2377
--
2378
-- In all cases, when concatenated these sub-sequences will be identical
2379
-- to the original ##source##.
2380
--
2381
--
2382
-- Example 1:
2383
--
2384
-- s = breakup("5545112133234454", 4)
2385
-- -- s is {"5545", "1121", "3323", "4454"}
2386
--
2387
--
2388
-- Example 2:
2389
--
2390
-- s = breakup("12345", 2)
2391
-- -- s is {"12", "34", "5"}
2392
--
2393
--
2394
-- Example 3:
2395
--
2396
-- s = breakup({1,2,3,4,5,6}, 3)
2397
-- -- s is {{1,2,3}, {4,5,6}}
2398
--
2399
--
2400
-- Example 4:
2401
--
2402
-- s = breakup("ABCDEF", 0)
2403
-- -- s is {"ABCDEF"}
2404
--
2405
--
2406
-- See Also:
2407
-- [[:split]] [[:flatten]]
2408
240922
2410
241122
if atom(size) and not integer(size) then
24120
size = floor(size)
2413
end if
2414
2415
-- Convert simple integer size into the 'customized' size format.
241622
if integer(size) then
241714
integer len
241814
integer rem
241914
if style = BK_LEN then
24206
if size < 1 or size >= length(source) then
24213
return {source}
2422
end if
24233
len = floor(length(source) / size)
24243
rem = remainder(length(source), size)
24253
size = repeat(size, len)
24263
if rem > 0 then
24271
size &= rem
2428
end if
2429
else
24308
if size > length(source) then
24312
size = length(source)
2432
end if
24338
if size < 1 then
24342
return {source}
2435
end if
24366
len = floor(length(source) / size)
24376
if len < 1 then
24380
len = 1
2439
end if
24406
rem = length(source) - (size * len)
24416
size = repeat(len, size)
24426
for i = 1 to length(size) do
244310
if rem = 0 then
24446
exit
2445
end if
24464
size[i] += 1
24474
rem -= 1
24484
end for
2449
end if
2450
end if
2451
2452
2453
-- Allocate the top level sequence.
245417
sequence ns = repeat(0, length(size))
245517
integer source_idx = 1
2456
2457
-- Place each source element into its appropriate target sub-sequence.
245817
for i = 1 to length(size) do
245942
if source_idx <= length(source) then
246040
integer k = 1
246140
ns[i] = repeat(0, size[i])
246240
for j = 1 to size[i] do
246390
if source_idx > length(source) then
24641
ns[i] = ns[i][1 .. k-1]
24651
exit
2466
end if
246789
ns[i][k] = source[source_idx]
246889
k += 1
246989
source_idx += 1
247089
end for
2471
else
24722
ns[i] = {}
2473
end if
247442
end for
2475
2476
--Handle any leftover data from source.
247717
if source_idx <= length(source) then
24784
ns = append(ns, source[source_idx .. $])
2479
end if
2480
248117
return ns
2482
end function
2483
2484
--**
2485
-- Remove all nesting from a sequence.
2486
--
2487
-- Parameters:
2488
-- # ##s## : the sequence to flatten out.
2489
-- # ##delim## : An optional delimiter to place after each flattened sub-sequence (except
2490
-- the last one).
2491
--
2492
-- Returns:
2493
-- A **sequence**, of atoms, all the atoms in ##s## enumerated.
2494
--
2495
-- Comments:
2496
-- * If you consider a sequence as a tree, then the enumeration is performed
2497
-- by left-right reading of the tree. The elements are simply read left to
2498
-- right, without any care for braces.
2499
-- * Empty sub-sequences are stripped out entirely.
2500
--
2501
-- Example 1:
2502
--
2503
-- s = flatten({{18, 19}, 45, {18.4, 29.3}})
2504
-- -- s is {18, 19, 45, 18.4, 29.3}
2505
--
2506
--
2507
-- Example 2:
2508
--
2509
-- s = flatten({18,{ 19, {45}}, {18.4, {}, 29.3}})
2510
-- -- s is {18, 19, 45, 18.4, 29.3}
2511
--
2512
--
2513
-- Example 3:
2514
--
2515
-- Using the delimiter argument.
2516
-- s = flatten({"abc", "def", "ghi"}, ", ")
2517
-- -- s is "abc, def, ghi"
2518
--
2519
2520
2521241
2522
sequence ret
2523
object x
2524
integer len
2525
integer pos
2526
2527241
if atom(delim) then
25281
delim = {delim}
2529
end if
2530241
ret = s
2531241
pos = 1
2532241
len = length(ret)
2533241
while pos <= len do
25346336
x = ret[pos]
25356336
if sequence(x) then
2536221
if length(delim) = 0 then
253724
ret = ret[1..pos-1] & flatten(x) & ret[pos+1 .. $]
2538
else
2539197
sequence temp = ret[1..pos-1] & flatten(x)
2540197
if pos != length(ret) then
2541182
ret = temp & delim & ret[pos+1 .. $]
2542
else
254315
ret = temp & ret[pos+1 .. $]
2544
end if
2545
end if
2546221
len = length(ret)
2547
else
25486115
pos += 1
2549
end if
25506336
end while
2551
2552241
return ret
2553
end function
2554
2555
2556
--**
2557
-- Returns a sequence of three sub-sequences. The sub-sequences contain
2558
-- all the elements less than the supplied pivot value, equal to the pivot,
2559
-- and greater than the pivot.
2560
--
2561
-- Parameters:
2562
-- # ##data_p## : Either an atom or a list. An atom is treated as if it is one-element sequence.
2563
-- # ##pivot_p## : An object. Default is zero.
2564
--
2565
-- Returns:
2566
-- A **sequence**, { {less than pivot}, {equal to pivot}, {greater than pivot} }
2567
--
2568
-- Comments:
2569
-- ##pivot()## is used as a split up a sequence relative to a specific value.
2570
--
2571
-- Example 1:
2572
--
2573
-- ? pivot( {7, 2, 8.5, 6, 6, -4.8, 6, 6, 3.341, -8, "text"}, 6 )
2574
-- -- Ans: {{2, -4.8, 3.341, -8}, {6, 6, 6, 6}, {7, 8.5, "text"}}
2575
-- ? pivot( {4, 1, -4, 6, -1, -7, 9, 10} )
2576
-- -- Ans: {{-4, -1, -7}, {}, {4, 1, 6, 9, 10}}
2577
-- ? pivot( 5 )
2578
-- -- Ans: {{}, {}, {5}}
2579
--
2580
--
2581
-- Example 2:
2582
--
2583
-- function quiksort(sequence s)
2584
-- if length(s) < 2 then
2585
-- return s
2586
-- end if
2587
-- sequence k
2588
--
2589
-- k = pivot(s, s[rand(length(s))])
2590
--
2591
-- return quiksort(k[1]) & k[2] & quiksort(k[3])
2592
-- end function
2593
-- sequence t2 = {5,4,7,2,4,9,1,0,4,32,7,54,2,5,8,445,67}
2594
-- ? quiksort(t2) --> {0,1,2,2,4,4,4,5,5,7,7,8,9,32,54,67,445}
2595
--
2596
2597
25987
2599
sequence result_
2600
integer pos_
2601
26027
result_ = {{}, {}, {}}
2603
26047
if atom(data_p) then
26053
data_p = {data_p}
2606
end if
2607
26087
for i = 1 to length(data_p) do
260927
pos_ = eu:compare(data_p[i], pivot_p) + 2
261027
result_[pos_] = append(result_[pos_], data_p[i])
261127
end for
2612
26137
return result_
2614
end function
2615
2616
2617
--**
2618
-- Implements "List Comprehension" or building a list based on the contents of another list.
2619
--
2620
-- Parameters:
2621
-- # ##source## : A sequence. The list of items to base the new list upon.
2622
-- # ##transformer## : One or more routine_ids. These are [[:routine_id | routine ids]]
2623
-- of functions that must receive three parameters (object x, sequence i, object u)
2624
-- where 'x' is an item in the ##source## list, 'i' contains the position that 'x' is
2625
-- found in the ##source## list and the length of ##source##, and 'u'
2626
-- is the ##user_data## value. Each transformer
2627
-- must return a two-element sequence. If the first element is zero, then build_list() continues
2628
-- on with the next transformer function for the same 'x'. If the first element is not
2629
-- zero, the second element is added to the new list being built (other elements
2630
-- are ignored) and build_list skips the rest of the transformers and processes
2631
-- the next element in ##source##.
2632
-- # ##singleton## : An integer. If zero then the transformer functions return multiple
2633
-- list elements. If not zero then the transformer functions return
2634
-- a single item (which might be a sequence).
2635
-- # ##user_data## : Any object. This is passed unchanged to each transformer function.
2636
--
2637
-- Returns:
2638
-- A **sequence**, The new list of items.
2639
--
2640
-- Comments:
2641
-- * If the transformer is -1, then the source item is just copied.
2642
--
2643
-- Example 1:
2644
--
2645
-- function remitem(object x, sequence i, object q)
2646
-- if (x < q) then
2647
-- return {0} -- no output
2648
-- else
2649
-- return {1,x} -- copy 'x'
2650
-- end if
2651
-- end function
2652
--
2653
-- sequence s
2654
-- -- Remove negative elements (x < 0)
2655
-- s = build_list({-3, 0, 1.1, -2, 2, 3, -1.5}, routine_id("remitem"), , 0)
2656
-- -- s is {0, 1.1, 2, 3}
2657
--
2658
26596
26606
sequence result = {}
2661
sequence x
2662
object new_x
2663
2664
-- Special case where only one transformer is supplied.
26656
if integer(transformer) then
26664
transformer = {transformer}
2667
end if
2668
26696
for i = 1 to length(source) do
267041
x = {source[i], {i, length(source)}, user_data}
2671
267241
for j = 1 to length(transformer) do
2673
267449
if transformer[j] >= 0 then
267540
new_x = call_func(transformer[j], x)
267640
if length(new_x) = 0 then
2677
-- This didn't return anything so go to the next transformer.
26782
continue
2679
end if
268038
if new_x[1] = 0 then
2681
-- This didn't return anything so go to the next transformer.
268214
continue
2683
end if
268424
if new_x[1] < 0 then
2685
-- This didn't return anything and skip other transformers.
26860
exit
2687
end if
2688
268924
new_x = new_x[2]
2690
else
2691
-- Just copy the input.
26929
new_x = x[1]
2693
end if
2694
269533
if singleton then
269618
result = append(result, new_x)
2697
else
269815
result &= new_x
2699
end if
2700
2701
-- Stop calling any more transformers for this input item.
270233
exit
2703
27040
end for
2705
2706
270741
end for
2708
27096
return result
2710
end function
2711
2712
--**
2713
-- Transforms the input sequence by using one or more user-supplied transformers.
2714
--
2715
-- Parameters:
2716
-- # ##source_data## : A sequence to be transformed.
2717
-- # ##transformer_rids## : An object. One or more routine_ids used to transform the input.
2718
--
2719
-- Returns:
2720
-- The source **sequence**, that has been transformed.
2721
--
2722
-- Comments:
2723
-- * This works by calling each transformer in order, passing to it the result
2724
-- of the previous transformation. Of course, the first transformer gets the
2725
-- original sequence as passed to this routine.
2726
-- * Each transformer routine takes one or more parameters. The first is a source sequence
2727
-- to be transformed and others are any user data that may have been supplied
2728
-- to the ##transform## routine.
2729
-- * Each transformer routine returns a transformed sequence.
2730
-- * The ##transformer_rids## parameters is either a single routine_id or a sequence
2731
-- of routine_ids. In this second case, the routine_id may actually be a
2732
-- multi-element sequence containing the real routine_id and some user data to
2733
-- pass to the transformer routine. If there is no user data then the transformer
2734
-- is called with only one parameter.
2735
--
2736
-- Examples:
2737
--
2738
-- res = transform(" hello ", {
2739
-- {routine_id("trim"), " ",0},
2740
-- routine_id("upper"),
2741
-- {routine_id("replace_all"), "O", "A"}
2742
-- })
2743
-- --> "HELLA"
2744
--
2745
27462
2747
sequence lResult
2748
27492
lResult = source_data
27502
if atom(transformer_rids) then
27511
transformer_rids = {transformer_rids}
2752
end if
2753
27542
for i = 1 to length(transformer_rids) do
27554
if atom(transformer_rids[i]) then
27562
lResult = call_func(transformer_rids[i], {lResult})
2757
else
27582
lResult = call_func(transformer_rids[i][1], {lResult} & transformer_rids[i][2..$])
2759
end if
27604
end for
27612
return lResult
2762
2763
end function
2764
2765
--**
2766
-- Calculates the similarity between two sequences.
2767
--
2768
-- Parameters:
2769
-- # ##A## : A sequence.
2770
-- # ##B## : A sequence.
2771
--
2772
-- Returns:
2773
-- An **atom**, the closer to zero, the more the two sequences are alike.
2774
--
2775
-- Comments:
2776
-- The calculation is weighted to give mismatched elements towards the front
2777
-- of the sequences larger scores. This means that sequences that differ near
2778
-- the begining are considered more un-alike than mismatches towards the end of
2779
-- the sequences. Also, unmatched elements from the first sequence are weighted more
2780
-- than unmatched elements from the second sequence.
2781
--
2782
-- Two identical sequences return zero. A non-zero means that they are not the same
2783
-- and larger values indicate a larger differences.
2784
--
2785
-- Example 1:
2786
--
2787
-- ? sim_index("sit", "sin") --> 0.08784
2788
-- ? sim_index("sit", "sat") --> 0.32394
2789
-- ? sim_index("sit", "skit") --> 0.34324
2790
-- ? sim_index("sit", "its") --> 0.68293
2791
-- ? sim_index("sit", "kit") --> 0.86603
2792
--
2793
-- ? sim_index("knitting", "knitting") --> 0.00000
2794
-- ? sim_index("kitting", "kitten") --> 0.09068
2795
-- ? sim_index("knitting", "knotting") --> 0.27717
2796
-- ? sim_index("knitting", "kitten") --> 0.35332
2797
-- ? sim_index("abacus","zoological") --> 0.76304
2798
--
2799
28004
2801
atom accum_score
2802
atom pos_factor
2803
integer indx_a
2804
integer indx_b
2805
sequence used_A
2806
sequence used_B
2807
2808
-- First pass scores only matching runs of elements.
28094
accum_score = 0
28104
indx_a = 1
28114
used_A = repeat(0, length(A))
28124
used_B = repeat(0, length(B))
28134
while indx_a <= length(A) label "DoA" do
28149
pos_factor = power((1 + length(A) - indx_a) / length(A),2)
28159
indx_b = 1
28169
while indx_b <= length(B) do
281719
if equal(A[indx_a],B[indx_b]) then
28187
accum_score += power((indx_b - indx_a) * pos_factor,2)
28197
while indx_a <= length(A) and indx_b <= length(B) with entry do
28206
if not equal(A[indx_a], B[indx_b]) then
28213
exit
2822
end if
2823
entry
282410
used_B[indx_b] = 1
282510
used_A[indx_a] = 1
282610
indx_a += 1
282710
indx_b += 1
282810
end while
28297
continue "DoA"
2830
end if
283112
indx_b += 1
283212
end while
28332
indx_a += 1
28342
end while
2835
2836
-- Now score the unused elements from A.
28374
for i = 1 to length(A) do
283812
if used_A[i] = 0 then
28392
pos_factor = power((1 + length(A) - i) / length(A),2)
28402
accum_score += power((length(A) - i + 1) * pos_factor,2)
2841
end if
284212
end for
2843
2844
-- Now score the unused elements from B.
28454
integer total_elems = length(A)
28464
for i = 1 to length(B) do
284713
if used_B[i] = 0 then
28483
pos_factor = power((1 + length(B) - i) / length(B),2)
28493
accum_score += (length(B) - i + 1) * pos_factor
28503
total_elems += 1
2851
end if
285213
end for
2853
28544
return power(accum_score / power(total_elems,2), 0.5)
2855
end function
2856
2857
--**
2858
-- Indicates that [[:remove_subseq]]() must not replace removed sub-sequences
2859
-- with an alternative value.
2860101
public constant SEQ_NOALT = {{1.23456}}
2861
2862
2863
--**
2864
-- Removes all sub-sequences from the supplied sequence, optionally
2865
-- replacing them with a supplied alternative value. One common use
2866
-- is to remove all strings from a mixed set of numbers and strings.
2867
--
2868
-- Parameters:
2869
-- # ##source_list## : A sequence from which sub-sequences are removed.
2870
-- # ##alt_value## : An object. The default is SEQ_NOALT, which causes sub-sequences
2871
-- to be physically removed, otherwise any other value will be
2872
-- used to replace the sub-sequence.
2873
--
2874
-- Returns:
2875
-- A **sequence**, which contains only the atoms from ##source_list## and optionally
2876
-- the ##alt_value## where sub-sequences used to be.
2877
--
2878
-- Example:
2879
--
2880
-- sequence s = remove_subseq({4,6,"Apple",0.1, {1,2,3}, 4})
2881
-- -- 's' is now {4, 6, 0.1, 4} -- length now 4
2882
-- s = remove_subseq({4,6,"Apple",0.1, {1,2,3}, 4}, -1)
2883
-- -- 's' is now {4, 6, -1, 0.1, -1, 4} -- length unchanged.
2884
--
2885
--
2886
288722
2888
sequence lResult
288922
integer lCOW = 0
2890
289122
for i = 1 to length(source_list) do
289290
if atom(source_list[i]) then
289370
if lCOW != 0 then
289410
if lCOW != i then
28958
lResult[lCOW] = source_list[i]
2896
end if
289710
lCOW += 1
2898
end if
289970
continue
2900
end if
2901
290220
if lCOW = 0 then
290316
lResult = source_list
290416
lCOW = i
2905
end if
290620
if not equal(alt_value, SEQ_NOALT) then
29075
lResult[lCOW] = alt_value
29085
lCOW += 1
2909
end if
2910
291120
end for
2912
291322
if lCOW = 0 then
29146
return source_list
2915
end if
291616
return lResult[1.. lCOW - 1]
2917
end function
2918
2919
--**
2920
-- These are used with the [[:remove_dups]]() function.
2921
-- ** RD_INPLACE removes items while preserving the original order of the unique items.
2922
-- ** RD_PRESORTED assumes that the elements in ##source_data## are already sorted. If they
2923
-- are not already sorted, this option merely removed adjacent duplicate elements.
2924
-- ** RD_SORT will return the unique elements in ascending sorted order.
2925
2926
public enum
2927101
RD_INPLACE,
2928101
RD_PRESORTED,
2929101
RD_SORT
2930
2931
--**
2932
-- Removes duplicate elements
2933
--
2934
-- Parameters:
2935
-- # ##source_data## : A sequence that may contain duplicated elements
2936
-- # ##proc_option## : One of RD_INPLACE, RD_PRESORTED, or RD_SORT.
2937
-- ** RD_INPLACE removes items while preserving the original order of the unique items.
2938
-- ** RD_PRESORTED assumes that the elements in ##source_data## are already sorted. If they
2939
-- are not already sorted, this option merely removed adjacent duplicate elements.
2940
-- ** RD_SORT will return the unique elements in ascending sorted order.
2941
--
2942
-- Returns:
2943
-- A **sequence**, that contains only the unique elements from ##source_data##.
2944
--
2945
-- Example 1:
2946
--
2947
-- sequence s = { 4,7,9,7,2,5,5,9,0,4,4,5,6,5}
2948
-- ? remove_dups(s, RD_INPLACE) --> {4,7,9,2,5,0,6}
2949
-- ? remove_dups(s, RD_SORT) --> {0,2,4,5,6,7,9}
2950
-- ? remove_dups(s, RD_PRESORTED) --> {4,7,9,7,2,5,9,0,4,5,6,5}
2951
-- ? remove_dups(sort(s), RD_PRESORTED) --> {0,2,4,5,6,7,9}
2952
--
2953
--
295417
2955
integer lTo
2956
integer lFrom
2957
295817
if length(source_data) < 2 then
29593
return source_data
2960
end if
2961
296214
if proc_option = RD_SORT then
296311
source_data = sort(source_data)
296411
proc_option = RD_PRESORTED
2965
end if
296614
if proc_option = RD_PRESORTED then
296713
lTo = 1
296813
lFrom = 2
2969
297013
while lFrom <= length(source_data) do
2971108
if not equal(source_data[lFrom], source_data[lTo]) then
297249
lTo += 1
297349
if lTo != lFrom then
297434
source_data[lTo] = source_data[lFrom]
2975
end if
2976
end if
2977108
lFrom += 1
2978108
end while
297913
return source_data[1 .. lTo]
2980
end if
2981
29821
sequence lResult
29831
lResult = {}
29841
for i = 1 to length(source_data) do
298514
if not find(source_data[i], lResult) then
29867
lResult = append(lResult, source_data[i])
2987
end if
298814
end for
29891
return lResult
2990
2991
end function
2992
2993
public enum
2994101
COMBINE_UNSORTED = 0,
2995101
COMBINE_SORTED,
2996
$
2997
2998
--**
2999
-- Combines all the sub-sequences into a single, optionally sorted, list
3000
--
3001
-- Parameters:
3002
-- # ##source_data## : A sequence that contains sub-sequences to be combined.
3003
-- # ##proc_option## : An integer; COMBINE_UNSORTED to return a non-sorted list and
3004
-- COMBINE_SORTED (the default) to return a sorted list.
3005
--
3006
-- Returns:
3007
-- A **sequence**, that contains all the elements from all the first-level of
3008
-- sub-sequences from ##source_data##.
3009
--
3010
-- Comments:
3011
-- The elements in the sub-sequences do not have to be pre-sorted.
3012
--
3013
-- Only one level of sub-sequence is combined.
3014
--
3015
-- Example 1:
3016
--
3017
-- sequence s = { {4,7,9}, {7,2,5,9}, {0,4}, {5}, {6,5}}
3018
-- ? combine(s, COMBINE_SORTED) --> {0,2,4,4,5,5,5,6,7,7,9,9}
3019
-- ? combine(s, COMBINE_UNSORTED) --> {4,7,9,7,2,5,9,0,4,5,6,5}
3020
--
3021
--
3022
-- Example 2:
3023
--
3024
-- sequence s = { {"cat", "dog"}, {"fish", "whale"}, {"wolf"}, {"snail", "worm"}}
3025
-- ? combine(s) --> {"cat","dog","fish","snail","whale","wolf","worm"}
3026
-- ? combine(s, COMBINE_UNSORTED) --> {"cat","dog","fish","whale","wolf","snail","worm"}
3027
--
3028
--
3029
-- Example 3:
3030
--
3031
-- sequence s = { "cat", "dog","fish", "whale", "wolf", "snail", "worm"}
3032
-- ? combine(s) --> "aaacdeffghhiilllmnooorsstwww"
3033
-- ? combine(s, COMBINE_UNSORTED) --> "catdogfishwhalewolfsnailworm"
3034
--
3035
--
30368
3037
sequence lResult
30388
integer lTotalSize = 0
3039
integer lPos
3040
30418
if length(source_data) = 0 then
30421
return {}
3043
end if
3044
30457
if length(source_data) = 1 then
30461
return source_data[1]
3047
end if
3048
30496
for i = 1 to length(source_data) do
305032
lTotalSize += length(source_data[i])
305132
end for
3052
30536
lResult = repeat(0, lTotalSize)
30546
lPos = 1
30556
for i = 1 to length(source_data) do
305632
lResult[lPos .. length(source_data[i]) + lPos - 1] = source_data[i]
305732
lPos += length(source_data[i])
305832
end for
3059
30606
if proc_option = COMBINE_SORTED then
30613
return sort(lResult)
3062
else
30633
return lResult
3064
end if
3065
end function
3066
3067
--/desc Pads /i source_data to the right until its length reaches /i min_size using /i new_data as filler.
3068
--/ret The padded sequence, unchanged if its size was not less than /i min_size on input.
3069
--**
3070
-- Ensures that the supplied sequence is at least the supplied minimum length.
3071
--
3072
-- Parameters:
3073
-- # ##source_data## : A sequence that might need extending.
3074
-- # ##min_size##: An integer. The minimum length that ##source_data## must be.
3075
-- # ##new_data##: An object. This used to when ##source_data## needs to be extended,
3076
-- in which case it is appended as many times as required to make the length
3077
-- equal to ##min_size##.
3078
--
3079
-- Returns:
3080
-- A **sequence**.
3081
--
3082
-- Example:
3083
--
3084
-- sequence s
3085
-- s = minsize({4,3,6,2,7,1,2}, 10, -1) --> {4,3,6,2,7,1,2,-1,-1,-1}
3086
-- s = minsize({4,3,6,2,7,1,2}, 5, -1) --> {4,3,6,2,7,1,2}
3087
--
3088
--
30892
3090
30912
if length(source_data) < min_size then
30921
source_data &= repeat(new_data, min_size - length(source_data))
3093
end if
3094
30952
return source_data
3096
end function
3097