Làm cách nào để biến% s thành {0}, {1} Hãy bớt lộn xộn?


11

Tôi phải lấy một chuỗi chứa giữ chỗ để thay thế sau này, như:

"A %s B %s"

Và biến nó thành:

"A {0} B {1}"

Tôi đến với:

def _fix_substitution_parms(raw_message):
  rv = raw_message
  counter = 0
  while '%s' in rv:
    rv = rv.replace('%s', '{' + str(counter) + '}', 1)
    counter = counter + 1
return rv

Điều đó làm việc, nhưng nó cảm thấy siêu cồng kềnh, và không phải là con trăn "thành ngữ".

Làm thế nào một giải pháp trăn tốt, thành ngữ sẽ trông như thế nào?

Cập nhật để làm rõ:

  • các chuỗi kết quả không được sử dụng trong python. Tôi làm cần những con số truy cập trong đó! (như vậy {}là không đủ tốt)!
  • Tôi chỉ cần quan tâm đến các %schuỗi, vì các tin nhắn được đảm bảo chỉ sử dụng %s(không có %i %fgì)

"Re.sub" có thể lấy chức năng thay thế để thay thế động bằng niềng răng được đánh số. Nhân tiện: Thay thế bằng {} không có số cũng sẽ hoạt động.
Michael Butscher

3
Khi bạn có một giải pháp hiệu quả và bạn muốn cải thiện nó, vui lòng xem xét codereview.stackexchange.com
kojiro

@kojiro Nó không hoạt động đối với tôi, do "quá vụng về" ;-)
GhostCat chào mừng Monica C.

Câu trả lời:


5

Tôi sẽ làm những gì Reznik đề xuất ban đầu và sau đó kêu gọi .format:

def _fix_substitution_parms(raw_message: str) -> str:
    num_to_replace = raw_message.count("%s")
    python_format_string_message = raw_message.replace("%s", "{{{}}}")
    final_message = python_format_string_message.format(*range(num_to_replace))
    return final_message

Điều này sẽ chỉ hoạt động nếu bạn có 2 %strong văn bản?
Charif DZ

@CharifDZ và Aran-Fey - xem bản chỉnh sửa. Bạn chỉ cần đếm chúng trước khi ra tay ...
Dan

Trông giống như một sự thỏa hiệp tốt ... có thể đọc được, nhưng không quá màu mè.
GhostCat chào mừng Monica C.

8

Sử dụng re.subvới hàm lambda để áp dụng lại thay thế một lần cho mỗi phần tử và itertools.countđể nhận số liên tiếp:

import itertools
import re

s = "A %s B %s"

counter = itertools.count()
result = re.sub('%s', lambda x: f'{{{next(counter)}}}', s)
print(result)  # 'A {0} B {1}'

Hãy nhớ bọc nó trong một chức năng để thực hiện thao tác này nhiều lần, vì bạn sẽ cần làm mới itertools.count.


Thật tuyệt, mặc dù tôi thấy nó hơi "tối nghĩa" ;-)
GhostCat chào mừng Monica C.

@GhostCat nó không tối nghĩa, bộ đếm là một trình tạo khi bạn gọi next(counter)nó tạo ra giá trị tiếp theo, tôi luôn quên câu trả lời này rất hay
Charif DZ

@GhostCat regex và lập trình chức năng trong cùng một dòng: -PI đoán "sự tối nghĩa" phụ thuộc vào mức độ bạn đã sử dụng cho các công cụ này.
jfaccioni

3

Tôi nghĩ rằng shoudl làm việc

rv.replace('%s','{{{}}}').format(*range(rv.count('%s')))


1
@GhostCat không bị cám dỗ bởi một người lót, hãy nhớ rằng mọi người phải duy trì mã
Dan

1
@ Tôi biết. Nhưng tôi ít mã cũng ít mã hơn để duy trì.
GhostCat chào mừng Monica C.

Mặc dù vậy, nó không khó để gỡ lỗi và khó đọc hơn cho một nhà phát triển trong tương lai. Câu trả lời này khá gần giống với câu trả lời của tôi, nó có cùng các lệnh gọi (hoán đổi thay thế cho tách và nối) nhưng nếu có vấn đề trong bước trung gian thì sao? Làm thế nào bạn sẽ cô lập nó. Và nhanh hơn là ra dev mới để hiểu những gì nó làm chỉ từ mã. Tôi thực sự khuyên bạn không nên đặt nhiều logic này trong một dòng.
Dan

1
Không phải là một lót tốt đẹp. X.join(Y.split(Z))chỉ là một cách viết phức tạp Y.replace(X, Z)và không cần phải thực hiện rangecuộc gọi list(...).
Aran-Fey

1
@Dan vâng, xin lỗi về điều đó, (chỉ trong một dòng bây giờ) :)
Reznik

1

Sử dụng re.subđể thay thế động:

import re

text = "A %s B %s %s B %s"


def _fix_substitution_parms(raw_message):
    counter = 0
    def replace(_):
        nonlocal counter
        counter += 1
        return '{{{}}}'.format(counter - 1)
    return re.sub('%s', replace, raw_message)


print(_fix_substitution_parms(text))  # A {0} B {1} {2} B {3}

1
Hãy nhớ rằng điều này không giải thích cho các trình giữ chỗ đã thoát ( %%s) - nếu đó là vấn đề đáng lo ngại, bạn có thể sử dụng biểu thức chính quy r'(?<!%)%s'thay thế.
Aran-Fey

Nếu bạn cho phép câu hỏi ngu ngốc: {{{}}}thực sự là về cái gì?
GhostCat chào mừng Monica C.

Chuỗi hình thành để thoát {chúng ta không làm \{như bình thường chúng ta làm {{.
Charif DZ

1

Sử dụng máy phát điện:

def split_and_insert(mystring):
    parts = iter(mystring.split('%s'))
    yield next(parts)
    for n, part in enumerate(parts):
        yield f'{{{n}}}'
        yield part

new_string = ''.join(split_and_insert("A %s B %s"))

-4

Bạn đã thử với .format?

chuỗi.format (0 = giá trị, 1 = giá trị)

Vì thế:

"A {0} B {1}".format(0=value, 1=value)


1
Làm thế nào điều này giúp bất cứ ai biến %sthành {}?
Aran-Fey
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.