[comp.sys.mac.hypercard] How to find fields that DO NOT contain a string?

mike@ymt.com (Michael Czeiszperger) (06/11/91)

The find command in hypercard 2.x seems to be fairly lacking.  Does
anyone know a way to find fields that don't contain a certain
string without going to each card and checking?  Is there a commercial
or PD find replacement that will do this?

Thanks,


-- 
Michael Czeiszperger  | "I'm trying to teach a caveman to play scrabble
mike@ymt.com          | but the only word he is knows is 'uugh', and he
Greenbrae, CA         | doesn't know how to spell it!"

gdavis@primate.wisc.edu (Gary Davis) (06/12/91)

From article <mike.676657839@ushi>, by mike@ymt.com (Michael Czeiszperger):
> The find command in hypercard 2.x seems to be fairly lacking.  Does
> anyone know a way to find fields that don't contain a certain
> string without going to each card and checking?  Is there a commercial
> or PD find replacement that will do this?

I haven't tried it, but I think the following should work:

     mark all cards
     unmark cards by finding "your string"

You can then peruse the remaining marked cards with

     go to first marked card
     go to next marked card
     etc

Gary Davis

mike@ymt.com (Michael Czeiszperger) (06/12/91)

Besides the basic telling whether a field does or does not contain
a certain string, I'm also looking to find a way for the user
to implement complicated searches without scripting.  In a videotape
collection stack for instance, the user might want to find all
videotapes released by TouchStone Pictures between 1989-1990 that 
are under 2 hours long.  Writing a script won't work because the
search criteria would change each time.


-- 
Michael Czeiszperger  | "I'm trying to teach a caveman to play scrabble
mike@ymt.com          | but the only word he is knows is 'uugh', and he
Greenbrae, CA         | doesn't know how to spell it!"

gdavis@primate.wisc.edu (Gary Davis) (06/13/91)

From article <4500@uakari.primate.wisc.edu>, by gdavis@primate.wisc.edu (Gary Davis):
> From article <mike.676657839@ushi>, by mike@ymt.com (Michael Czeiszperger):
>> The find command in hypercard 2.x seems to be fairly lacking.  Does
>> anyone know a way to find fields that don't contain a certain
>> string without going to each card and checking?  Is there a commercial
>> or PD find replacement that will do this?
> 
> I haven't tried it, but I think the following should work:
> 
>      mark all cards
>      unmark cards by finding "your string"
> 
Well I tried it and it works fine. It took about 20 secs to mark all
cards not containg "Smith" in a database of about 5000 names. I mention
this because another approach suggested was to use the following statement:

     mark cards where "your string" is not in field "Foo"

I tried it on Smith and found it took about 5 minutes.

Where the string was a city name found on a majority of the cards, the
unmark approach took much longer, about 2.5 minutes, though the "where"
approach was still slower.

Incidently, I've just started playing with Reports 2.0 from Nine to Five
Software. It has a good report generator and a neat spreadsheet like
window for viewing a table generated from records in a HyperCard stack.
It's very fast. In the spreadsheet view I selected all records which
didn't contain the city name. It took Reports only 15 seconds to come
up with the list, where HyperCard itself took 2.5 minutes. How can it
be so much faster?

Gary Davis

gdavis@primate.wisc.edu (Gary Davis) (06/13/91)

From article <mike.676744632@ymt>, by mike@ymt.com (Michael Czeiszperger):
> Besides the basic telling whether a field does or does not contain
> a certain string, I'm also looking to find a way for the user
> to implement complicated searches without scripting.  In a videotape
> collection stack for instance, the user might want to find all
> videotapes released by TouchStone Pictures between 1989-1990 that 
> are under 2 hours long.  Writing a script won't work because the
> search criteria would change each time.

There are various ways to set up forms which a user could use to
set up complicated queries.

One way is to have a card with the same fields as occur on the regular
collection cards. In your example, the user could just type something
like "TouchStone Pictures" or "=TouchStone Pictures" or "<>TouchStone
Pictures" in the "Producer" field and "< 2" in the Length field. The
search script would use the values in the fields to carry out the
search. 

Another approach is to use popup menus to supply the couplers: "is",
"is not", "contains", "less than", etc, so the user doesn't have
to know what to type in the fields.

The scripting to carry out a search based on the entries in the search
card can get somewhat complicated, but needn't be too bad. One way
is to use "mark cards where" followed by a statement containg all the
conditions, such as,

     mark cards where field "Producer" = "Touchstone" and field "Length"
     < 2

Instead of actual values in the statement you would use variables
set from the fields on the search card.

It may be more efficient in many cases to first "find" the cards where
"Touchstone" is in "Producer" then check on the other conditions. Like
this:

     put "Producer" into fieldToSearch
     put "Touchstone Pictures" into whatToFind
     put 2 into condition
     put "<" into comparisonOperator
     put "Length" into theField
     -- get these from the search card

     put "field" && theField && comparisonOperator && condition
          into conditionStatement
 
     unmark all cards
     mark cards by finding whatToFind in field whatToSearch
     unmark cards where value of conditionStatement is not true

     -- the conditionStatement could obviously be more complicated

If you want to browse through cards rather than mark them all first,
it would probably better to do a standard "find" followed by a check
on the other conditions

on goToNextCardMeetingCriteria

     repeat
          find whatToFind in field whatToSearch
          if the result is not empty then exit repeat -- exit if not found
          if value of conditionStatement then exit repeat

          -- to avoid an potentially infinite loop you would
          -- also need something like this
          if firstCardFound is empty then
               put number of this card into firstCardFound
          else
               if number of this card is firstCardFound then exit repeat
          end if
          -- firstCardFound would need to be a global and to be
          -- set to empty before entering loop
     end repeat

end goToNextCardMeetingCriteria


You might also want to look at the commercial product "Reports 2.0." It
provides easy to use and fast methods for carrying out searches of
essentially arbitrary complexity.

Gary Davis

mike@ymt.com (Michael Czeiszperger) (06/18/91)

gdavis@primate.wisc.edu (Gary Davis) writes:
>Well I tried it and it works fine. It took about 20 secs to mark all
>cards not containg "Smith" in a database of about 5000 names. I mention
>this because another approach suggested was to use the following statement:

>     mark cards where "your string" is not in field "Foo"

>I tried it on Smith and found it took about 5 minutes.

I'm trying to set up a system where the stack user picks the search
criteria.  The "mark cards" syntax is supposed to be:

mark cardexpr where expr

You would think expr could be a variable containing a syntax structure,
but this is not the case.  As a workaround, I actually have to generate
the script for the mark call from the search script, and then execute it!

>[...] It took Reports only 15 seconds to come
>up with the list, where HyperCard itself took 2.5 minutes. How can it
>be so much faster?

I noticed this too.  Maybe they should sell the faster bit as another
XCMD?

-- 
Michael Czeiszperger  | "I'm trying to teach a caveman to play scrabble
mike@ymt.com          | but the only word he is knows is 'uugh', and he
Greenbrae, CA         | doesn't know how to spell it!"

mike@ymt.com (Michael Czeiszperger) (06/18/91)

gdavis@primate.wisc.edu (Gary Davis) writes:
>Another approach is to use popup menus to supply the couplers: "is",
>"is not", "contains", "less than", etc, so the user doesn't have
>to know what to type in the fields.

I found this to be the best, or at least my favorite.

>The scripting to carry out a search based on the entries in the search
>card can get somewhat complicated, but needn't be too bad. One way
>is to use "mark cards where" followed by a statement containg all the
>conditions, such as,

>     mark cards where field "Producer" = "Touchstone" and field "Length"
>     < 2
>Instead of actual values in the statement you would use variables
>set from the fields on the search card.
I not only want to be able to set what fields to search for what
text, but also complicated and's, or's, and nots.  The problem is
you can't have the mark expression after the where be a variable -
it just doesn't work.  Instead, I've head to generate a function,
stick it in the background, and call it every time I want to
do a search.

-- 
Michael Czeiszperger  | "I'm trying to teach a caveman to play scrabble
mike@ymt.com          | but the only word he is knows is 'uugh', and he
Greenbrae, CA         | doesn't know how to spell it!"