2017-06-26 23 views
7

Trong python có chức năng đẹp (str .format) có thể thực sự dễ dàng thay thế các biến (được mã hóa như {variable}) trong chuỗi có giá trị được lưu trữ trong dict (với giá trị được đặt tên theo tên biến). Cũng giống như vậy:Có R tương đương với chức năng chuỗi định dạng của python không?

vars=dict(animal="shark", verb="ate", noun="fish") 
string="Sammy the {animal} {verb} a {noun}." 
print(string.format(**vars)) 

Sammy cá mập ăn một con cá.

Giải pháp đơn giản nhất trong R là gì? Có một hàm 2-đối số tương đương được tích hợp có một chuỗi có các biến được mã hóa trong cùng một cách cách và thay thế chúng bằng các giá trị được đặt tên từ tên list?

Nếu không có chức năng tích hợp trong R, có một trong một gói đã xuất bản không?

Nếu không có gói nào trong gói được xuất bản, bạn sẽ sử dụng cái nào để viết một gói?

Quy tắc: chuỗi được cung cấp cho bạn với các biến được mã hóa như "{variable}". Các biến phải được mã hóa dưới dạng list. Tôi sẽ trả lời với phiên bản tùy chỉnh của tôi, nhưng sẽ chấp nhận một câu trả lời tốt hơn tôi.

+2

Tôi sẽ tự tin dán cổ ra và nói "không". Không được xây dựng trong cơ sở R. Có thể có một cái gì đó chính xác như thế này trong các gói phần mềm bổ sung. Có những thứ * tương tự để thực hiện thay thế biến (ví dụ như gói sản phẩm bia) nhưng bạn muốn định dạng chính xác được mã hóa với cú pháp {name} này, vâng? – Spacedman

+0

Có; chuỗi đã được xây dựng để phân tích python-centric, vì vậy tôi không thể thay đổi cách các biến được mã hóa. – nsheff

+0

'brew' sử dụng' <%=' and '%> 'làm điểm đánh dấu. Thay thế '{' và '}' bằng những cái sẽ làm việc nếu bạn không mong đợi '<% =' trong chuỗi hoặc đã thoát '{}' ở bất kỳ đâu. – Spacedman

Trả lời

2

Vì nó xuất hiện tôi không thể tìm thấy một built-in hoặc thậm chí một gói với chức năng như vậy, tôi đã cố gắng để cuộn của riêng tôi. Chức năng của tôi dựa trên gói stringi. Dưới đây là những gì tôi đã đưa ra:

strformat = function(str, vals) { 
    vars = stringi::stri_match_all(str, regex = "\\{.*?\\}", vectorize_all = FALSE)[[1]][,1] 
    x = str 
    for (i in seq_along(names(vals))) { 
     varName = names(vals)[i] 
     varCode = paste0("{", varName, "}") 
     x = stringi::stri_replace_all_fixed(x, varCode, vals[[varName]], vectorize_all = TRUE) 
    } 
    return(x) 
} 

Ví dụ:

> str = "Sammy the {animal} {verb} a {noun}." 
> vals = list(animal="shark", verb="ate", noun="fish") 

> strformat(str, vals) 
[1] "Sammy the shark ate a fish." 
3

Dưới đây là một chức năng có thể chuyển đổi các {}-<%=%> và sau đó sử dụng brew từ gói brew (mà bạn cần để cài đặt):

form = function(s,...){ 
s = gsub("\\}", "%>", gsub("\\{","<%=",s)) 
e = as.environment(list(...)) 
parent.env(e)=.GlobalEnv 
brew(text=s, envir=e) 
} 

Kiểm tra:

> form("Sammy the {animal} {verb} a {noun}.", animal = "shark", verb="made", noun="car") 
Sammy the shark made a car. 
> form("Sammy the {animal} {verb} a {noun}.", animal = "shark", verb="made", noun="truck") 
Sammy the shark made a truck. 

Nó sẽ thất bại nếu có bất kỳ { trong chuỗi định dạng mà không đánh dấu thay thế thay đổi, hoặc nếu nó có <%= hoặc bất kỳ các dấu brew cú pháp khác trong đó.

+0

Điều này ngắn gọn hơn phiên bản của tôi - nhưng tôi nghĩ sẽ hữu ích hơn nếu nó chấp nhận một 'danh sách' của các biến – nsheff

+1

Thử' form = function (s, L) {'và' e = as.environment (L) 'trong trường hợp đó (chưa được kiểm tra). Tôi đã căn cứ vào phương pháp định dạng chuỗi python của nó mà không thực sự có một dict, nhưng một danh sách đối số (mà bạn có thể chuyển đổi với các ngôi sao, như OP bây giờ đã thực hiện trong một chỉnh sửa! – Spacedman

+0

Yep, mà làm việc. – nsheff

7

tôi tìm thấy một giải pháp: gói keo từ tidyverse: https://github.com/tidyverse/glue

Một ví dụ:

library(glue) 
animal <- "shark" 
verb <- "ate" 
noun <- "fish" 
string="Sammy the {animal} {verb} a {noun}." 
glue(string) 
Sammy the shark ate a fish. 

Nếu bạn nhấn mạnh vào việc có danh sách các biến, bạn có thể làm:

l <- list(animal = "shark", verb = "ate", noun = "fish") 
do.call(glue, c(string , l)) 
Sammy the shark ate a fish. 

Kính trọng

Paweł

1

Gói stringrgần như có thay thế chính xác trong chức năng str_interp.nó chỉ đòi hỏi một chút điều chỉnh:

fmt = function(str, vals) { 
    # str_interp requires variables encoded like ${var}, so we substitute 
    # the {var} syntax here. 
    x = stringr::str_replace_all(x, "\\{", "${") 
    stringr::str_interp(x, args) 
} 
Các vấn đề liên quan