/R/strapplyc.R

http://gsubfn.googlecode.com/ · R · 64 lines · 52 code · 6 blank · 6 comment · 14 complexity · 5f1fb2943fb3dfc9b9bb8f2f39fdc693 MD5 · raw file

  1. library(tcltk)
  2. # x is name of a tcl variable holding list of character vectors
  3. tclList2R <- function(x, convert = as.character) {
  4. len <- as.integer(.Tcl(sprintf("llength $%s", x)))
  5. f <- function(i) convert(.Tcl(sprintf("lindex $%s %d", x, i)))
  6. lapply(seq(0, len-1), f)
  7. }
  8. # high performance strapply with hard coded FUN=c. Guts in tcl.
  9. strapplyc <- function(X, pattern, backref, ignore.case = FALSE, simplify = FALSE, USE.NAMES = FALSE, engine = getOption("gsubfn.engine")) {
  10. if (identical(engine, "R")) return(
  11. strapply(X = X, pattern = pattern, FUN = "c", backref = backref,
  12. ignore.case = ignore.case, simplify = simplify,
  13. USE.NAMES = USE.NAMES, engine = engine)
  14. )
  15. tcl("set", "X", as.tclObj(X))
  16. tcl("set", "pattern", pattern)
  17. tcl("set", "nocase", if (ignore.case) "-nocase" else "")
  18. if (missing(backref) || is.null(backref) || is.na(backref)) backref <- 999
  19. tcl("set", "backref", backref)
  20. .Tcl("set about [regexp -about -- $pattern]")
  21. .Tcl("set about [lindex $about 0]")
  22. .Tcl("if { min($about, $backref) <= 0 } { set mn 0 } else { set mn 1 }")
  23. .Tcl("set mx [expr min($about, abs($backref))]")
  24. s <- paste('set result {}
  25. set k [expr $about + 1]
  26. if { $about == 0 || $about <= -$backref} {
  27. # this leg of the "if" returns everything from regexp so we
  28. # can avoid the extraction subloop of the "else" leg for speed
  29. foreach item $X {
  30. # {*} is new feature in tcl 8.5 to add level of substitution
  31. set cmd [list regexp -all -inline {*}$nocase -- $pattern $item]
  32. set res [{*}$cmd]
  33. lappend result $res
  34. }
  35. } else {
  36. foreach item $X {
  37. # {*} is new feature in tcl 8.5 that adds level of substitution
  38. set cmd [list regexp -all -inline {*}$nocase -- $pattern $item]
  39. set cmdout [{*}$cmd]
  40. set imin $mn
  41. set imax $mx
  42. set res {}
  43. while {$imax < [llength $cmdout]} {
  44. lappend res [lrange $cmdout $imin $imax]
  45. incr imin $k
  46. incr imax $k
  47. }
  48. lappend result [concat {*}$res]
  49. }
  50. }')
  51. .Tcl(s)
  52. out <- tclList2R("result")
  53. result <- sapply(out, identity, simplify = isTRUE(simplify),
  54. USE.NAMES = USE.NAMES)
  55. if (is.logical(simplify)) result else {
  56. do.call(match.funfn(simplify), result)
  57. }
  58. }