Summary
###########################################################################
File: lists.icn
Subject: Procedures to manipulate lists
Author: Ralph E. Griswold
Date: June 11, 2001
###########################################################################
This file is in the public domain.
###########################################################################
Contributor: Richard L. Goerwitz
###########################################################################
file2lst(s) create list from lines in file
imag2lst(s) convert limage() output to list
l_Bscan(e1) begin list scanning
l_Escan(l_OuterEnvir, e2)
end list scanning
l_any(l1,l2,i,j)
any() for list scanning
l_bal(l1,l2,l3,l,i,j
bal() for list scanning
l_find(l1,l2,i,j)
find() for list scanning
l_many(l1,l2,i,j)
many() for list scanning
l_match(l1,l2,i,j)
match() for list scanning
l_move(i) move() for list scanning
l_pos(i) pos() for list scanning
l_tab(i) tab() for list scanning
l_upto(l1,l2,i,j)
upto() for list scanning
lclose(L) close open palindrome
lcomb(L,i) list combinations
lcompact(L) compact list, mapping out missing values
ldecollate(I, L)
list decollation
ldelete(L, spec)
list deletion
ldupl(L, i) list term duplication
lequiv(L1, L2) list equivalence
levate(L, m, n) list elevation
lextend(L, i) list extension
lfliph(L) list horizontal flip (reversal)
lflipv(L) list vertical flip
limage(L) unadorned list image
lcollate(L1, L2, ...)
list collation; like linterl() except stops on
short list
lconstant(L) succeeds and returns element if all are the same
linterl(L1, L2) list interleaving
llayer(L1, L2, ...)
layer and interleave L1, L2, ...
llpad(L, i, x) list padding at left
lltrim(L, S) list left trimming
lmap(L1,L2,L3) list mapping
lpalin(L, x) list palindrome
lpermute(L) list permutations
lreflect(L, i) returns L concatenated with its reversal to produce
palindrome; the values of i determine "end
conditions" for the reversal:
0 omit first and last elements; default
1 omit first element
2 omit last element
3 don't omit element
lremvals(L, x1, x2, ...)
remove values from list
lrepl(L, i) list replication
lresidue(L, m, i)
list residue
lreverse(L) list reverse
lrotate(L, i) list rotation
lrpad(L, i, x) list right padding
lrundown(L1, L2, L3)
list run down
lrunup(L1, L2, L3)
list run up
lrtrim(L, S) list right trimming
lshift(L, i) shift list terms
lswap(L) list element swap
lunique(L) keep only unique list elements
lmaxlen(L, p) returns the size of the largest value in L.
If p is given, it is applied to each string as
as a "length" procedure. The default for p is
proc("*", 1).
lminlen(L, p) returns the size of the smallest value in L.
If p is given, it is applied to each string as
as a "length" procedure. The default for p is
proc("*", 1).
sortkeys(L) returns list of keys from L, where L is the
result of sorting a table with option 3 or 4.
sortvalues(L) return list of values from L, where L is the
result of sorting a table with option 3 or 4.
str2lst(s, i) creates list with i-character lines from s. The
default for i is 1.
###########################################################################
About List Mapping
The procedure lmap(L1,L2,L3) maps elements of L1 according to L2
and L3. This procedure is the analog for lists of the built-in
string-mapping function map(s1,s2,s3). Elements in L1 that are
the same as elements in L2 are mapped into the corresponding ele-
ments of L3. For example, given the lists
L1 := [1,2,3,4]
L2 := [4,3,2,1]
L3 := ["a","b","c","d"]
then
lmap(L1,L2,L3)
produces a new list
["d","c","b","a"]
Lists that are mapped can have any kinds of elements. The
operation
x === y
is used to determine if elements x and y are equivalent.
All cases in lmap are handled as they are in map, except that
no defaults are provided for omitted arguments. As with map, lmap
can be used for transposition as well as substitution.
Warning:
If lmap is called with the same lists L2 and L3 as in
the immediately preceding call, the same mapping is performed,
even if the values in L2 and L3 have been changed. This improves
performance, but it may cause unexpected effects.
This ``caching'' of the mapping table based on L2 and L3
can be easily removed to avoid this potential problem.
###########################################################################
About List Scanning by Richard L. Goerwitz
PURPOSE: String scanning is terrific, but often I am forced to
tokenize and work with lists. So as to make operations on these
lists as close to corresponding string operations as possible, I've
implemented a series of list analogues to any(), bal(), find(),
many(), match(), move(), pos(), tab(), and upto(). Their names are
just like corresponding string functions, except with a prepended
"l_" (e.g. l_any()). Functionally, the list routines parallel the
string ones closely, except that in place of strings, l_find and
l_match accept lists as their first argument. L_any(), l_many(),
and l_upto() all take either sets of lists or lists of lists (e.g.
l_tab(l_upto([["a"],["b"],["j","u","n","k"]])). Note that l_bal(),
unlike the builtin bal(), has no defaults for the first four
arguments. This just seemed appropriate, given that no precise
list analogue to &cset, etc. occurs.
The default subject for list scans (analogous to &subject) is
l_SUBJ. The equivalent of &pos is l_POS. Naturally, these
variables are both global. They are used pretty much like &subject
and &pos, except that they are null until a list scanning
expression has been encountered containing a call to l_Bscan() (on
which, see below).
Note that environments cannot be maintained quite as elegantly as
they can be for the builtin string-scanning functions. One must
use instead a set of nested procedure calls, as explained in the
_Icon Analyst_ 1:6 (June, 1991), p. 1-2. In particular, one cannot
suspend, return, or otherwise break out of the nested procedure
calls. They can only be exited via failure. The names of these
procedures, at least in this implementation, are l_Escan and
l_Bscan. Here is one example of how they might be invoked:
suspend l_Escan(l_Bscan(some_list_or_other), {
l_tab(10 to *l_SUBJ) & {
if l_any(l1) | l_match(l2) then
old_l_POS + (l_POS-1)
}
})
Note that you cannot do this:
l_Escan(l_Bscan(some_list_or_other), {
l_tab(10 to *l_SUBJ) & {
if l_any(l1) | l_match(l2) then
suspend old_l_POS + (l_POS-1)
}
})
Remember, it's no fair to use suspend within the list scanning
expression. l_Escan must do all the suspending. It is perfectly OK,
though, to nest well-behaved list scanning expressions. And they can
be reliably used to generate a series of results as well.
###########################################################################
Here's another simple example of how one might invoke the l_scan
routines:
procedure main()
l := ["h","e","l","l","o"," ","t","t","t","h","e","r","e"]
l_Escan(l_Bscan(l), {
hello_list := l_tab(l_match(["h","e","l","l","o"]))
every writes(!hello_list)
write()
# Note the nested list-scanning expressions.
l_Escan(l_Bscan(l_tab(0)), {
l_tab(l_many([[" "],["t"]]) - 1)
every writes(!l_tab(0))
write()
})
})
end
The above program simply writes "hello" and "there" on successive
lines to the standard output.
###########################################################################
PITFALLS: In general, note that we are comparing lists here instead
of strings, so l_find("h", l), for instance, will yield an error
message (use l_find(["h"], l) instead). The point at which I
expect this nuance will be most confusing will be in cases where
one is looking for lists within lists. Suppose we have a list,
l1 := ["junk",[["hello"]," ",["there"]],"!","m","o","r","e","junk"]
and suppose, moreover, that we wish to find the position in l1 at
which the list
[["hello"]," ",["there"]]
occurs. If, say, we assign [["hello"]," ",["there"]] to the
variable l2, then our l_find() expression will need to look like
l_find([l2],l1)
###########################################################################
Extending scanning to lists is really very difficult. What I think
(at least tonight) is that scanning should never have been
restricted to strings. It should have been designed to operate on
all homogenous one-dimensional arrays (vectors, for you LISPers).
You should be able, in other words, to scan vectors of ints, longs,
characters - any data type that seems useful. The only question in
my mind is how to represent vectors as literals. Extending strings
to lists goes beyond the bounds of scanning per-se. This library is
therefore something of a stab in the dark.
###########################################################################
Links: equiv, indices, numbers
###########################################################################
Procedures:
file2lst, imag2lst, l_Bscan, l_Escan, l_any, l_bal, l_comp, l_find, l_many, l_match, l_move, l_pos, l_tab, l_upto, lblock, lclose, lcollate, lcomb, lcompact, lconstant, ldecollate, ldelete, ldupl, lequiv, levate, lextend, lfliph, lflipv, limage, linterl, llayer, llpad, lltrim, lmap, lmaxlen, lminlen, lpalin, lpermute, lreflect, lremvals, lrepl, lresidue, lreverse, lrotate, lrpad, lrtrim, lrundown, lrunup, lshift, lswap, lunique, sortkeys, sortvalues, str2lst
Records:
l_ScanEnvir
Global variables:
l_POS, l_SUBJ
Links:
equiv.icn, indices.icn, numbers.icn
This file is part of the (main) package.
Source code.
file2lst(s)
: create list from lines in file
imag2lst(seqimage)
: convert limage() output to list
l_Bscan(e1)
: begin list scanning
l_Escan(l_OuterEnvir, e2)
: end list scanning
l_any(l1, l2, i, j)
: any() for list scanning
l_bal(l1, l2, l3, l, i, j)
: bal() for list scanning
l_comp(l1, l2)
list comparison
l_find(l1, l2, i, j)
: find() for list scanning
l_many(l1, l2, i, j)
: many() for list scanning
l_match(l1, l2, i, j)
: match() for list scanning
l_move(i)
: move() for list scanning
l_pos(i)
: pos() for list scanning
l_tab(i)
: tab() for list scanning
l_upto(l1, l2, i, j)
: upto() for list scanning
lblock(L1, L2)
lclose(L)
: close open palindrome
lcollate(args)
: generalized list collation
lcomb(L, i)
: list combinations
lcompact(seq)
: compact sequence
lconstant(L)
: test list for all terms equal
ldecollate(indices, L)
: list decollation
ldelete(L, spec)
: delete specified list elements
ldupl(L1, L2)
: list term duplication
lequiv(x, y)
: compare lists for equivalence
levate(seq, m, n)
: elevate values
lextend(L, i)
: list extension
lfliph(L)
: list horizontal flip (reversal)
lflipv(L)
: list vertical flip
limage(L)
: list image
linterl(L1, L2)
: list interleaving
llayer(args)
: interleave lists with layering
llpad(L, i, x)
: list padding at left
lltrim(L, S)
: list left trimming
lmap(L1, L2, L3)
: list mapping
lmaxlen(L, p)
: size of largest list entry
lminlen(L, p)
: size of smallest list entry
lpalin(L, x)
: list palindrome
lpermute(L)
: list permutations
lreflect(L, i)
: list reflection
lremvals(L, x)
: remove values from list
lrepl(L, i)
: list replication
lresidue(L, m, i)
: list residue
lreverse(L)
: list reverse
lrotate(L, i)
: list rotation
lrpad(L, i, x)
: list right padding
lrtrim(L, S)
: list right trimming
lrundown(L1, L2, L3)
: list run up
lrunup(L1, L2, L3)
: list run up
lshift(L, i)
: shift list terms
lswap(L)
: list element swap
lunique(L)
: keep only unique list elements
sortkeys(L)
: extract keys from sorted list
sortvalues(L)
: extract values from sorted list
str2lst(s, i)
: list from string
l_ScanEnvir(subject, pos)
l_POS
l_SUBJ
This page produced by UniDoc on 2021/04/15 @ 23:59:54.