From: Phil Pennock <zsh-workers+phil.pennock@spodhuis.org>
To: Zsh hackers list <zsh-workers@sunsite.dk>
Subject: Set operations
Date: Sat, 27 Sep 2008 02:02:25 -0700 [thread overview]
Message-ID: <20080927090225.GA61785@redoubt.spodhuis.org> (raw)
Somehow, until a recent post from Bart, I'd missed ${array:#element} to
remove an element from an array. That was the clean removal method I'd
been missing for using -U unique arrays as sets.
So the below is a first pass implementation of set arithmetic; however,
the safesub stuff shows that my big problem is, when joining existing
elements together with |, escaping pattern-characters in the original
array elements. It does try to be fairly resistant to non-normal
setups without going full emulate, since it only uses a few features.
So given 'b' naming the set variable with the elements to remove, I do a
first pass approximation like this:
safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
instead of just, for set subtraction of b from a:
"${(P@)a:#${(Pj,|,)~b}}"
However, this obviously doesn't deal with the full set of
pattern-matching characters, so is incomplete.
So, before I head off and implement a parameter expansion flag to escape
pattern-matching characters (honouring current pattern-affecting
options), the question is whether I'm missing something obvious to do
this set arithmetic cleanly already, or if there's already a clean way
to escape pattern characters?
Any feedback on the complete set (so to speak) of functionality or
naming or implementation appreciated, with an eye to adding this to the
standard zsh install (autoloaded function set_operations to define
these?)
Or is the thing to do to overload the arithmetic operations in
arithmetic expansion, for let, to be able to handle -U arrays as sets
natively? :-) (let diff=a-b ...)
(The number of times I work with large lists of machines interactively
in shell and want to deal with them as sets and manipulate appropriately
is somewhat high and I'm fed up of switching to Python.)
Regards,
-Phil
#----------------------------8< cut here >8------------------------------
function newset {
setopt local_options no_ksh_arrays
local name="$1"; shift
typeset -gUa $name
set -A $name "$@"
}
function copyset_tofrom {
setopt local_options no_ksh_arrays
local new="$1" old="$2"
typeset -gUa $new
set -A $new "${(P@)old}"
}
function copyset_fromto { copyset_tofrom "$2" "$1" }
function set_add_new {
setopt local_options no_ksh_arrays
local new="$1" a="$2" b="$3"
typeset -gUa $new
set -A $new "${(P@)a}" "${(P@)b}"
}
function set_add_in {
setopt local_options no_ksh_arrays
local name="$1" b="$2"
set -A $name "${(P@)name}" "${(P@)b}"
}
function set_add_print {
setopt local_options no_ksh_arrays
local a="$1" b="$2"
typeset -Ua tmp
tmp=("${(P@)a}" "${(P@)b}")
print -r -- ${(q)tmp}
}
function set_subtract_new {
setopt local_options no_ksh_arrays
local new="$1" a="$2" b="$3"
typeset -gUa $new
typeset -Ua safesub
safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
set -A $new "${(P@)a:#${(j,|,)~safesub}}"
}
function set_subtract_in {
setopt local_options no_ksh_arrays
local name="$1" b="$2"
typeset -Ua safesub
safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
set -A $name "${(P@)name:#${(j,|,)~safesub}}"
}
function set_subtract_print {
setopt local_options no_ksh_arrays
local a="$1" b="$2"
typeset -Ua tmp
typeset -Ua safesub
safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
tmp=("${(P@)a:#${(j,|,)~safesub}}")
print -r -- ${(q)tmp}
}
function set_intersection_new {
setopt local_options no_ksh_arrays
local new="$1" a="$2" b="$3"
typeset -gUa $new
typeset -Ua safesub
safesub=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
set -A $new "${(@PM)a:#${(j,|,)~safesub}}"
}
function set_union_new { set_add_new "$@" }
function set_union_in { set_add_in "$@" }
function set_union_print { set_add_print "$@" }
function set_difference_new { set_subtract_new "$@" }
function set_difference_in { set_subtract_in "$@" }
function set_difference_print { set_subtract_print "$@" }
function set_symmetric_difference_new {
setopt local_options no_ksh_arrays
local new="$1" a="$2" b="$3"
typeset -gUa $new
typeset -Ua safe_a safe_b
safe_b=("${(@)${(@)${(@)${(P@)a//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
safe_b=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
set -A $new "${(P@)a:#${(j,|,)~safe_b}}" "${(P@)b:#${(j,|,)~safe_a}}"
}
function set_symmetric_difference_in {
setopt local_options no_ksh_arrays
local name="$1" b="$2"
typeset -Ua safe_name safe_b
safe_a=("${(@)${(@)${(@)${(P@)a//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
safe_b=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
set -A $name "${(P@)name:#${(j,|,)~safe_b}}" "${(P@)b:#${(j,|,)~safe_name}}"
}
function set_symmetric_difference_print {
setopt local_options no_ksh_arrays
local a="$1" b="$2"
typeset -Ua tmp
typeset -Ua safe_a safe_b
safe_b=("${(@)${(@)${(@)${(P@)a//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
safe_b=("${(@)${(@)${(@)${(P@)b//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
tmp=("${(P@)a:#${(j,|,)~safe_b}}" "${(P@)b:#${(j,|,)~safe_a}}")
print -r -- ${(q)tmp}
}
function set_insert_list {
setopt local_options no_ksh_arrays
local name="$1"; shift
set -A $name "${(P@)name}" "$@"
}
function set_remove_list {
setopt local_options no_ksh_arrays
local name="$1"; shift
typeset -Ua safesub
safesub=("${(@)${(@)${(@)${(P)@//\\/\\\\}//\|/\\|}//\?/\\?}//\*/\\*}")
set -A $name "${(P@)name:#${(j,|,)~safesub}}"
}
#----------------------------8< cut here >8------------------------------
next reply other threads:[~2008-09-27 9:03 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-27 9:02 Phil Pennock [this message]
2008-09-27 20:48 ` Peter Stephenson
2008-09-28 1:50 ` Phil Pennock
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080927090225.GA61785@redoubt.spodhuis.org \
--to=zsh-workers+phil.pennock@spodhuis.org \
--cc=zsh-workers@sunsite.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).