Re: Q: what is a fast way to see if an 'item' is present in an array?

2016-02-16 Thread Martijn Dekker
Linda Walsh schreef op 16-02-16 om 04:59:
> w/the slow func  being killed by a $() sub process, likely:

Yes, subshells are fatal for performance, particularly on bash.

> my fn2='() {my t="${2:?}[*]"
>my arRE="^($(IFS="|"; echo "${!t}"))$"
>[[ $1 =~ $arRE ]]
> }
> '

(What's "my"? An alias for "local"?)

Try this:

appears_in() {
local IFS="|" val="$1"
shift
[[ "$IFS$*$IFS" == *"$IFS$val$IFS"* ]]
}
if appears_in "somevalue" "${array[@]}"; then do stuff; fi

For anyone reading who may not know, the trick is that "$*" expands to a
single string containing all the positional parameters separated by the
first character of $IFS (or with no separator if IFS is empty, but
that's not useful here).

Of course this function is dependent on none of the elements containing
"|". But this lets you set any separator you want, so you could use a
really unlikely character such as IFS=$'\1'.

- M.




Re: Q: what is a fast way to see if an 'item' is present in an array?

2016-02-16 Thread strombrg
On Monday, February 15, 2016 at 7:59:35 PM UTC-8, Linda Walsh wrote:
> I has a little 4 line func that returns true or false
> if a string was in an array

Arrays aren't really a great datastructure for testing presence and absence in.

An associative array / dictionary / hash is better.

Consider:
http://stromberg.dnsalias.org/~strombrg/database/


Re: Q: what is a fast way to see if an 'item' is present in an array?

2016-02-16 Thread Linda Walsh



Greg Wooledge wrote:

On Mon, Feb 15, 2016 at 07:59:21PM -0800, Linda Walsh wrote:
  

Obviously, If I could precook the array into
a hash, I'd think it would be faster... but
the "cooking part", I think, is the high
overhead part.



Redesign the entire script so that you use the associative array (hash)
from the beginning instead of, or in addition to, storing your information
in a "list" (indexed array).
  

It would also take throwing away previous cfg-file compat as well
as changing the linux kernel interface.  Somehow I don't think that
is going to be easier:


 (cd /sys/class/net/br0/brif/; echo *)

eth0 eth5

 grep  ^BRIDGE_PORTS "$CFG"

BRIDGE_PORTS='eth0 eth5'

---
In my case it's only 2, but other interfaces... still not that long
*usually*,

 (cd $PWD/holders; echo *)

dm-0 dm-1 dm-12 dm-2 dm-3 dm-4 dm-5 dm-6 dm-7 dm-8 dm-9

But I tend to think about worst case behaviors and at least
try to ask around if anyone has anything better... but in this case,
the impact is minimal.

Though when designing 'anew', I try to make things data/table
driven as much as possible for things that fit into that paradigm.

Thanks!
L.












Re: Q: what is a fast way to see if an 'item' is present in an array?

2016-02-16 Thread Greg Wooledge
On Mon, Feb 15, 2016 at 07:59:21PM -0800, Linda Walsh wrote:
> Obviously, If I could precook the array into
> a hash, I'd think it would be faster... but
> the "cooking part", I think, is the high
> overhead part.

Redesign the entire script so that you use the associative array (hash)
from the beginning instead of, or in addition to, storing your information
in a "list" (indexed array).



Q: what is a fast way to see if an 'item' is present in an array?

2016-02-15 Thread Linda Walsh

I has a little 4 line func that returns true or false
if a string was in an array

I came up with a different way of doing it, that I
though might be faster... but...
putting them in a file and running loops on them.
(times below).  Obviously, my feeling for what might
be faster was way wrong. w/my 2nd method
being 15-44X slower depending on where the match is.

Obviously, If I could precook the array into
a hash, I'd think it would be faster... but
the "cooking part", I think, is the high
overhead part.

The fast function was:
my fn1='() {
   my __
   my t="${2:?}[@]"
   for __ in "${!t}"; do [[ $1 == "$__" ]] && return 0;done
   return 1;
}
'
w/the slow func  being killed by a $() sub process, likely:
my fn2='() {   
 my t="${2:?}[*]"

   my arRE="^($(IFS="|"; echo "${!t}"))$"
   [[ $1 =~ $arRE ]]
}
'

Was wondering if anyone else had fast functions like this
to determine if a string is in a list?

I can attach the test script (doubles as an "include" or
"source" file), if people want to test their own...
The frameworks should be simple to copy in other test
functions...(or replace #2...)...

This was in bash-4.3.42.

---data results---



(-t [#loops] string WORDLIST):

so false case 1st:
 _in.shh -t 300 word {0..999} 

func(fn1): 1.49sec 1.48usr 0.00sys (100.02% cpu)
false
func(fn2): 22.78sec 18.38usr 4.32sys (99.69% cpu)
false

then true w/match @ end of the list

_in.shh -t 300 word {0..999} word
func(fn1): 1.49sec 1.49usr 0.00sys (100.03% cpu)
true
func(fn2): 22.85sec 18.46usr 4.31sys (99.67% cpu)
true

then true w/match @ beginning of list...


 _in.shh -t 300 word word {0..999}

func(fn1): 0.51sec 0.51usr 0.00sys (100.01% cpu)
true
func(fn2): 22.75sec 18.40usr 4.28sys (99.70% cpu)
true