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

[append][series]Appending to a series of strings

 [1/7] from: joel::neely::fedex::com at: 18-Nov-2003 7:19


Hi Seth, See below... Seth wrote:
> >> a: [1 2 3 4 5] > == [1 2 3 4 5]
<<quoted lines omitted: 4>>
> >> append b/:x "hi" > == "hi"
At this point, take a look at the value of B to see why:
>> b
== ["hi"]
>> fourth b
** Script Error: Out of range or past end ** Near: fourth b
>> >> b/:x
== none
>> > >> x: index? find a 4 > == 4
At this point B has no fourth element (ergo B/:X returns NONE) so...
> >> append b/:x "hi" > ** Script Error: append expected series argument of type: series port > ** Near: append b/:x "hi" > > In theory, shouldn't append do it's thing on b/4 ... What's with the > error? :\ >
...you can't treat that (non-existent) element as a series. Unlike Perl, which automatically allocates and meaningfully initializes previously non-existent data, REBOL requires that a value exist and be of the correct type for whatever operation you attempt to perform on it. -jn-

 [2/7] from: seth:chromick:earthlink at: 18-Nov-2003 9:53


Joel Neely wrote:
>Hi Seth, >See below...
<<quoted lines omitted: 38>>
>of the correct type for whatever operation you attempt to perform on it. >-jn-
Thanks everyone... I was coming from a Perl point of view here -- The REBOL way is a lot more logical -- This is what I get for coding at ungodly hours in the morning ;] Thanks... :D

 [3/7] from: joel:neely:fedex at: 18-Nov-2003 11:07


Hi, Seth, Seth wrote:
> Joel Neely wrote: >>...you can't treat that (non-existent) element as a series.
<<quoted lines omitted: 5>>
> REBOL way is a lot more logical -- This is what I get for coding at > ungodly hours in the morning ;] Thanks... :D
IMHO neither more nor less logical, just differently logical. Suppose one has a collection of small natural numbers (such as test scores ranging from 0 to 100) and one wants to know how many occurrences of each distinct number there are. Using Perl arrays: # assume @scores contains the raw data with dups @tallies = (); foreach $score (@scores) { ++$tallies[$score]; } foreach $score (0..$#tallies) { print "$score: $tallies[$score]\n" if $tallies[$score]; } Using REBOL blocks: ; assume SCORES contains the raw data with dups tallies: [] foreach score scores [ insert/dup tail tallies 0 score + 1 - length? tallies change at tallies score + 1 1 + pick tallies score + 1 ] forall tallies [ if 0 < tallies/1 [print [-1 + index? tallies ":" tallies/1]] ] or ; assume SCORES contains the raw data with dups tallies: [] foreach score scores [ either found? here: select tallies score [ here/1: here/1 + 1 ][ append tallies reduce [score copy [1]] ] ] foreach [score tally] sort/skip tallies 2 [ print [score ";" tally/1] ] REBOL is much more "literal"; there are no values that one does not explicitly create (although it is possible to be implicitly explicit at times ;-). On the other hand, it is necessary explicitly to manage details that aren't at the same logical level as the original problem (making sure that there enough "places" to store the next tally needed, etc). I'd be interested in any *self-contained* solutions to the above task that might be clearer than the above. -jn- -- ---------------------------------------------------------------------- Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1

 [4/7] from: antonr:iinet:au at: 20-Nov-2003 16:11



 [5/7] from: lmecir:mbox:vol:cz at: 20-Nov-2003 12:14


Hi, my solution using Parse (I think, that it is much faster, than other solutions): scores: clear [] loop 30 [append scores random 20] group: [p: set i integer! any i q: (print ["score:" i "tallies:" offset? p q])] parse probe sort scores [any group] Anton Rolls napsal(a):

 [6/7] from: brett:codeconscious at: 20-Nov-2003 22:43


Hi Ladislav,
> Hi, my solution using Parse (I think, that it is much faster, than other > solutions):
<<quoted lines omitted: 3>>
> offset? p q])] > parse probe sort scores [any group]
That was so lateral I fell over. Just brilliant. Regards, Brett.

 [7/7] from: joel:neely:fedex at: 20-Nov-2003 13:22


Hi, Ladislav, Actually, it's not faster (for sufficiently large cases). See below. Ladislav Mecir wrote:
> Hi, my solution using Parse (I think, that it is much faster, than > other solutions): >
I did a bit of benchmarking with functions that use each of the three strategies to generate a block of answers (value/count pairs). I'll include those functions at the end, in case anyone wants to verify that I didn't mangle any code. Using a SCORES block of random numbers between 0 and 100 (inclusive), the iterative version scales up better than the parse-based version as the size of the SCORES block increases (all times in seconds): size iterative remove-each parse-based 1000 1E-2 0.28 0 10000 0.351 2.874 0.24 100000 3.024 36.813 4.637 200000 4.787 -- 4.556 300000 6.74 -- 6.94 400000 8.832 -- 14.371 500000 11.887 -- 18.517 1000000 21.891 -- 39.227 I gave up VERY quickly on the remove-each-based version; it gets eaten alive by memory management overhead. Since the parse-based version sorts (a copy of) the scores block, its time complexity must be at least O (n log n). The iterative version is only O (n), so it will be faster for sufficiently large n. I should also point out that the iterative version requires only one value at a time; it can work on an arbitrarily large set of values (e.g., being retrieved across a network connection, read from a huge data file, resulting from computation in a loop, etc.), but the remove- and parse-based versions require the entire set to be available for sorting. There's one final point, but I'll post it separately. -jn- Ladislav Mecir wrote:
> scores: clear [] > loop 30 [append scores random 20]
<<quoted lines omitted: 17>>
>>] >>
SOURCE CODE FOR TIMED FUNCTIONS IS GIVEN BELOW: ;iterative version tally-i: func [ scores [block!] /local tallies result ][ tallies: copy [] foreach score scores [ either found? here: select tallies score [ here/1: here/1 + 1 ][ insert tail tallies reduce [score copy [1]] ] ] result: make block! length? tallies foreach [score tally] sort/skip tallies 2 [ insert tail result score insert tail result tally ] result ] ;remove-each-based version tally-r: func [ scores [block!] /local tallies ][ tallies: clear [] foreach uscore sort unique scores [ append/only tallies reduce [ uscore length? remove-each score copy scores [uscore <> score] ] ] ] ;parse-based version tally-p: func [ scores [block!] /local group p q result ][ result: copy [] group: [ p: set i integer! any i q: ( insert tail result i insert tail result offset? p q ) ] parse sort copy scores [any group] result ] -- ---------------------------------------------------------------------- Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446 Enron Accountingg in a Nutshell: 1c=$0.01=($0.10)**2=(10c)**2=100c=$1

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