Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Set operations
- X-seq: zsh-workers 25758
- From: Phil Pennock <zsh-workers+phil.pennock@xxxxxxxxxxxx>
- To: Zsh hackers list <zsh-workers@xxxxxxxxxx>
- Subject: Set operations
- Date: Sat, 27 Sep 2008 02:02:25 -0700
- Domainkey-signature: a=rsa-sha1; q=dns; c=nofws; s=d200807; d=spodhuis.org; h=Received:Date:From:To:Subject:Message-ID:Mail-Followup-To:MIME-Version:Content-Type:Content-Disposition; b=wM3iUEkqkdntPWe899ymc9Irmu1NsX+wx70V0fI3UNUJIujigFff6njOwmVnOg981ZZqcXLzRnDAK9kVCM+F5kOZviULqo0AS/G67vxTIAejtfEStTDkPvysTfqCIGQfW+HVtaZ+R/Se7pC5IuHoIygy6LFtB2DJKZAsdq+rdlk=;
- Mail-followup-to: Zsh hackers list <zsh-workers@xxxxxxxxxx>
- Mailing-list: contact zsh-workers-help@xxxxxxxxxx; run by ezmlm
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------------------------------
Messages sorted by:
Reverse Date,
Date,
Thread,
Author