Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Multi-searches

 [1/15] from: info:id-net:ch at: 20-Feb-2002 9:25


Hi all, I want to make multi-researches on a block of strings. The result I want is an array of index of all appereances of a name, but the 'find word find only the first appereance and to find the second appereance I have to find the index, then 'skip the list to index + 1 and so on.. Is there another way to make it, because in my case, sometimes the word to find is listed on second position of my array and sometimes on the third? So just to make those search I need 100 rows, and it's bugging! Philippe

 [2/15] from: joel:neely:fedex at: 20-Feb-2002 6:46


Hi, Philippe, Philippe Oehler wrote:
> I want to make multi-researches on a block of strings. > > The result I want is an array of index of all appereances of a name, > but the 'find word find only the first appereance >
Do you mean something like this?
>> blort: [1 2 0 3 0 4 5 6 0 7]
== [1 2 0 3 0 4 5 6 0 7]
>> find-all: func [b [block!] v [any-type!] /local result] [
[ result: copy [] [ forall b [if v = b/1 [append result index? b]] [ result [ ]
>> find-all blort 0
== [3 5 9] I used a block of numbers to save typing, but the principle is the same IMHO. HTH! -jn- -- ; sub REBOL {}; sub head ($) {@_[0]} REBOL [] # despam: func [e] [replace replace/all e ":" "." "#" "@"] ; sub despam {my ($e) = @_; $e =~ tr/:#/.@/; return "\n$e"} print head reverse despam "moc:xedef#yleen:leoj" ;

 [3/15] from: brett:codeconscious at: 21-Feb-2002 1:16


Hi Philippe, You can use find in a loop. Save the result of the previous find so that you do another find after the last one: find-multiple: function [ "Searches the series and returns the positions where the value occurs." series [series!] value [any-type!] ][result][ result: copy [] while [all [not tail? series found? series: find/only series value]][ insert tail result index? series series: next series ] result ] find-multiple ["red" "green" "blue" "red"] "red" Regards, Brett.

 [4/15] from: info:id-net:ch at: 20-Feb-2002 14:26


Hi Joel, Yes Joel something like that. Thanks a lot ! I tried with the FIND word but you just did with a IF test. Sometimes the things are more, more simple as you expected 8-) Can you explain me something ? Why (result) is a local variable and then without the RETURN word, you typed (result) at the end of the function ? What is the advantage of this ? Philippe

 [5/15] from: greggirwin:mindspring at: 20-Feb-2002 11:55


Hi Philippe, << Can you explain me something ? Why (result) is a local variable and then without the RETURN word, you typed (result) at the end of the function ? What is the advantage of this ? >> REBOL functions automatically return the last thing they evaluate. It's kind of a REBOL idiom *not* to use RETURN in that case, though I still haven't gotten my brain to do that very often. I believe it's more efficient not to use RETURN, so there is a "clear" argument for it as well. --Gregg

 [6/15] from: joel:neely:fedex at: 20-Feb-2002 13:32


Hi, Philippe, Philippe Oehler wrote:
> Can you explain me something ? Why (result) is a local variable > and then without the RETURN word, you typed (result) at the end > of the function ? >
The value returned from a function is the value of the last expression evaluated within the function. A single word is, of course, a trivial expression...
> What is the advantage of this ? >
The only reason for using RETURN is to force non-fall-through exit from a function. Putting it at the end of a function is just a wasted extra word evaluation (and typing) AFAIK. -jn-

 [7/15] from: info:id-net:ch at: 20-Feb-2002 22:26


Hi Brett, Could you explain me this line : while [all [not tail? series found? series: find/only series value]][ I use ALL like that "all [(first test)(second test)] [consequence]" but here ? and what does the rest of the line ? Philippe

 [8/15] from: jason:cunliffe:verizon at: 20-Feb-2002 16:53


Joel Neely <[joel--neely--fedex--com]> wrote:
> The only reason for using RETURN is to force non-fall-through > exit from a function. Putting it at the end of a function is > just a wasted extra word evaluation (and typing) AFAIK.
Joel That's interesting. Could you expand a little please.. What do you mean by "non-fall-through exit" ? thanks ./Jason

 [9/15] from: al:bri:xtra at: 21-Feb-2002 15:15


Philippe wrote:
> Could you explain me this line : > while [all [not tail? series found? series: find/only series value]][
Sometimes it helps to see it like: while [ all [ not tail? series found? series: find/only series value ] ][ ; and so on. Does that help make it clearer? Andrew Martin ICQ: 26227169 http://valley.150m.com/

 [10/15] from: joel:neely:fedex at: 20-Feb-2002 20:31


Hi, Jason, Jason Cunliffe wrote:
> That's interesting. Could you expand a little please.. > What do you mean by "non-fall-through exit" ? >
A "fall-through" exit is one that "falls" out of the end of the function. A non-fall-through exit terminates the function evaluation prior to reaching the end of the normal sequential flow. RETURN essentially acts as "go to the out door". Here's a strict one-way-out function to compute the real roots of a quadratic equation. If the discriminant is... ...there are _ real roots. ------------------------- -------------------------- negative no zero two equal positive two distinct 8<------------------------------------------------------------ quadform1: func [a [number!] b [number!] c [number!] /local d] [ d: b * b - (4.0 * a * c) either d < 0 [ [] ][ a: 1.0 / 2.0 / a b: - b either d = 0 [ reduce [b * a] ][ d: square-root d reduce [b + d * a b - d * a] ] ] ] 8<------------------------------------------------------------ Notice that this "purist" version uses nested conditions to evaluate only the appropriate expressions. In contrast: 8<------------------------------------------------------------ quadform2: func [a [number!] b [number!] c [number!] /local d] [ d: b * b - (4.0 * a * c) if d < 0 [return []] a: 1.0 / 2.0 / a b: - b if d = 0 [return reduce [b * a]] d: square-root d reduce [b + d * a b - d * a] ] 8<------------------------------------------------------------ the above version uses "early exits" via RETURN to bail out as soon as the result is determined. YMMV but some folks think that the second version is easier to read because of the absence of nesting. Of course these two are equivalent mod a trivial syntactic rewrite. Sometimes early exits make a significant difference in structure or performance. Consider a function that tests whether all numbers in a block are even: 8<------------------------------------------------------------ alleven1: func [blk [block!] /local evensofar] [ evensofar: true foreach nbr blk [ evensofar: evensofar and even? nbr ] evensofar ] 8<------------------------------------------------------------ That one is certainly correct, but may work more than necessary (since FALSE is a zero for AND). It can be written (at a cost of performance) to make explicit tests of both the state of the block and the state of the accumulator variable: 8<------------------------------------------------------------ alleven2: func [blk [block!] /local evensofar] [ evensofar: true while [all [not empty? blk evensofar]] [ evensofar: even? first blk blk: next blk ] evensofar ] 8<------------------------------------------------------------ ...but that's just clunky-looking. Both of those functions used fall-through exits, because they were structured to flow all the way to the end. If we take off our purist hats and take advantage of RETURN, we can write this as: 8<------------------------------------------------------------ alleven3: func [blk [block!]] [ foreach nbr blk [ if odd? nbr [return false] ] true ] 8<------------------------------------------------------------ The RETURN is necessary *inside* the loop to force early departure from the function. At the end, we only need to provide the (trivial) expression for the result. HTH! -jn- -- ; sub REBOL {}; sub head ($) {@_[0]} REBOL [] # despam: func [e] [replace replace/all e ":" "." "#" "@"] ; sub despam {my ($e) = @_; $e =~ tr/:#/.@/; return "\n$e"} print head reverse despam "moc:xedef#yleen:leoj" ;

 [11/15] from: chalz:earthlink at: 21-Feb-2002 0:01


I'm sure someone else has gotten to this already (I only get to my email about once every 24hrs), but in case someone else hasn't mentioned this, there's always the good old method of (I know this isn't all totally proper REBOL, or good code): test: x list: [a b c d ...] idxs: [] i: 0 foreach val list [ i: i + 1 if val = test [join idxs i] ] return idxs I'm sure there are far more elegant methods in REBOL, but, I was 'trained' in C and C-style systems.

 [12/15] from: carl:cybercraft at: 21-Feb-2002 19:56


On 21-Feb-02, Philippe Oehler wrote:
> Hi Joel, > Yes Joel something like that. Thanks a lot ! I tried with the FIND > word but you just did with a IF test. Sometimes the things are more, > more simple as you expected 8-)
Hi Philippe, Joel's answered you fine, but your question suggested another possible approach to me if (though only if) you were looking for series within a block. What the following does is to put what you're looking for in the block that's returned instead of the index numbers. It's easier to show you than explain I think, so... find-series: func [blk [block!] ser [series!] /local result][ result: copy [] forall blk [ if blk/1 = ser [append result blk/1] ] result ]
>> a: ["fe" "fi" "fo" "fe" "fi" "fo"]
== ["fe" "fi" "fo" "fe" "fi" "fo"]
>> b: find-series a "fo"
== ["fo" "fo"] The two "fo"s in 'b there are the same strings that appear in 'a, so that allows us to do the following kind of stuff...
>> append b/1 "1"
== "fo1"
>> a
== ["fe" "fi" "fo1" "fe" "fi" "fo"]
>> b
== ["fo1" "fo"] and...
>> append b/2 "2"
== "fo2"
>> a
== ["fe" "fi" "fo1" "fe" "fi" "fo2"]
>> b
== ["fo1" "fo2"] Hope that's of interest even if it's not of specific use to your current project.
> Can you explain me something ? Why (result) is a local variable and > then without the RETURN word, you typed (result) at the end of the
<<quoted lines omitted: 21>>
>> HTH! >> -jn-
-- Carl Read

 [13/15] from: brett:codeconscious at: 21-Feb-2002 20:44


Hi Philippe,
> Could you explain me this line : > while [all [not tail? series found? series: find/only series value]][
Andrew's formatting maybe have explained it for you, but if not, some more detail is below.
> I use ALL like that "all [(first test)(second test)] [consequence]" but
here
> ? and what does the rest of the line ?
First off, in case it helps, a quick correction to your example. ALL takes only one parameter, a block. The "[consequence]" part of your example is not used by ALL at all. Probably your example is part of an IF statement like this: IF condition [consequence] E.g:
>> if true [now]
== 21-Feb-2002/20:00:37+11:00
>> if all [1 2] [3]
== 3 Now on to ALL. ALL evalutes a block of expressions. If during that evaluation one of those expressions results in none! then ALL returns none!. If all the expressions are not none! then ALL returns the result of the last expression. Examples:
>> all [1 2 3 4 5]
== 5
>> all [1 2 now]
== 21-Feb-2002/19:50:44+11:00
>> all [1 2 none 4 5]
== none Back to my line. I intended this part of the line: [ not tail? series found? series: find/only series value ] to have two results. The first result is to make sure that there is something left to process. The second result is true only if the value is found in the the remaining part of the series. If either of these results in none! ALL will return none! and the while loop will stop. When both are true it means that I have a value to process. The second result may look odd to you. I didn't really need to use found? but I did to emphasize where the second result was going to come from. You can as easily delete "found?" from the line - the condition will still work. find/only series value finds the value in the series. If the value is found then the result of this is the same series but it's index (position) modified to where the value occurred. I capture this result into the same variable "series". If the value was not found you get a none! So the series index gets moved up if a value is found. It gets moved to the value. The body part of the while loop runs for each value that is found. It adds the value to the result and then it moves the series index again to prevent an infinite loop. I hope that is helpful! Regards, Brett.

 [14/15] from: joel:neely:fedex at: 21-Feb-2002 5:18


Hi, again, all, Minor quibble... Brett Handley wrote:
> ALL evalutes a block of expressions. If during that evaluation > one of those expressions results in none! >
... or FALSE ...
> then ALL returns none!. If all the expressions are not none! > then ALL returns the result of the last expression...
... so that it behaves somewhat like a generalized AND. -jn- -- ; sub REBOL {}; sub head ($) {@_[0]} REBOL [] # despam: func [e] [replace replace/all e ":" "." "#" "@"] ; sub despam {my ($e) = @_; $e =~ tr/:#/.@/; return "\n$e"} print head reverse despam "moc:xedef#yleen:leoj" ;

 [15/15] from: jason:cunliffe:verizon at: 23-Feb-2002 12:05


Joel Neely <[joel--neely--fedex--com]> wrote:
> > That's interesting. Could you expand a little please.. > > What do you mean by "non-fall-through exit" ? > > A "fall-through" exit is one that "falls" out of the end of the > function. A non-fall-through exit terminates the function > evaluation prior to reaching the end of the normal sequential > flow. RETURN essentially acts as "go to the out door".
etc..snip another great answer from Joel... Joel thanks again for a wonderful lesson! ./Jason

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted