web-dev-qa-db-ja.com

Rで文字列連結演算子を作成する

||のような文字列連結演算子をRで書くにはどうすればよいのだろうかと思っていました。 SASの場合、+ Java/C#の場合、または&VisualBasicの場合。

最も簡単な方法は、%を使用して次のような特別な演算子を作成することです。

`%+%` <- function(a, b) paste(a, b, sep="")

しかし、これはコードに多くの醜い%をもたらします。

+がOpsグループで定義されており、そのグループにS4メソッドを記述できることに気づきました。そのため、おそらくそのようなものが最適です。ただし、S4言語の機能についてはまったく経験がありません。 S4を使用するように上記の関数を変更するにはどうすればよいですか?

44
Hong Ooi

他の人が述べているように、封印されたS4メソッド「+」をオーバーライドすることはできません。ただし、文字列の加算関数を定義するために新しいクラスを定義する必要はありません。これは、文字列のクラスを変換する必要があり、コードがより醜くなるため、理想的ではありません。代わりに、単に「+」関数を上書きすることができます。

"+" = function(x,y) {
    if(is.character(x) || is.character(y)) {
        return(paste(x , y, sep=""))
    } else {
        .Primitive("+")(x,y)
    }
}

次に、以下はすべて期待どおりに機能するはずです。

1 + 4
1:10 + 4 
"Help" + "Me"

このソリューションは、形式手法を使用しなくなったため、ハックのように感じますが、必要な動作を正確に取得する唯一の方法です。

41
statsmaths

これを試してみます(比較的クリーンなS3ソリューション)

`+` <- function (e1, e2) UseMethod("+")
`+.default` <- function (e1, e2) .Primitive("+")(e1, e2)
`+.character` <- function(e1, e2) 
    if(length(e1) == length(e2)) {
           paste(e1, e2, sep = '')
    } else stop('String Vectors of Different Lengths')

上記のコードは、+をジェネリックに変更し、+.defaultを元の+に設定してから、新しいメソッド+.character+に追加します。

25
Lytze

これにはS3クラスを使用することもできます。

String <- function(x) {
  class(x) <- c("String", class(x))
  x
}

"+.String" <- function(x,...) {
  x <- paste(x, paste(..., sep="", collapse=""), sep="", collapse="")
  String(x)
}


print.String <- function(x, ...) cat(x)

x <- "The quick brown "
y <- "fox jumped over "
z <- "the lazy dog"

String(x) + y + z
23
jverzani

RがS4に完全に準拠する場合は、次の手順で十分です。

setMethod("+",
          signature(e1 = "character", e2 = "character"),
          function (e1, e2) {
              paste(e1, e2, sep = "")
      })

しかし、これはメソッドが封印されているというエラーを出します:((。うまくいけば、これはRの機能バージョンで変更されます。

最善の方法は、「文字」クラスとまったく同じように動作する新しいクラス「文字列」を定義することです。

setClass("string", contains="character")
string <- function(obj) new("string", as.character(obj))

そして、Rが許可する最も一般的な方法を定義します。

setMethod("+", signature(e1 = "character", e2 = "ANY"),
          function (e1, e2) string(paste(e1, as.character(e2), sep = "")))

今試してみてください:

tt <- string(44444)

tt
#An object of class "string"
#[1] "44444"
tt + 3434
#[1] "444443434"
"sfds" + tt
#[1] "sfds44444"
tt +  tt
#[1] "4444444444"
343 + tt
#Error in 343 + tt : non-numeric argument to binary operator
"sdfs" + tt + "dfsd"
#An object of class "string"
#[1] "sdfs44444dfsd"
11
VitoshKa

あなたは自分自身に正しい答えを与えました-Rのすべては関数であり、新しい演算子を定義することはできません。そう %+%それが得るのと同じくらい良いです。

8