Tất cả các câu trả lời ở đây đều không đạt một hoặc nhiều câu sau:
- Họ viết lại thứ gì đó (thật tệ!) Trong thư viện mẫu chuẩn (ack, câu trả lời hàng đầu!)
- Họ không sử dụng
and
cho mục cuối cùng.
- Chúng thiếu dấu phẩy nối tiếp (oxford).
- Chúng sử dụng lập chỉ mục phủ định, điều này sẽ không hoạt động đối với các bộ truy vấn django.
- Họ thường không xử lý vệ sinh chuỗi đúng cách.
Đây là mục nhập của tôi vào kinh điển này. Đầu tiên, các bài kiểm tra:
class TestTextFilters(TestCase):
def test_oxford_zero_items(self):
self.assertEqual(oxford_comma([]), '')
def test_oxford_one_item(self):
self.assertEqual(oxford_comma(['a']), 'a')
def test_oxford_two_items(self):
self.assertEqual(oxford_comma(['a', 'b']), 'a and b')
def test_oxford_three_items(self):
self.assertEqual(oxford_comma(['a', 'b', 'c']), 'a, b, and c')
Và bây giờ là mã. Có, nó hơi lộn xộn, nhưng bạn sẽ thấy rằng nó không sử dụng lập chỉ mục phủ định:
from django.utils.encoding import force_text
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
@register.filter(is_safe=True, needs_autoescape=True)
def oxford_comma(l, autoescape=True):
"""Join together items in a list, separating them with commas or ', and'"""
l = map(force_text, l)
if autoescape:
l = map(conditional_escape, l)
num_items = len(l)
if num_items == 0:
s = ''
elif num_items == 1:
s = l[0]
elif num_items == 2:
s = l[0] + ' and ' + l[1]
elif num_items > 2:
for i, item in enumerate(l):
if i == 0:
s = item
elif i == (num_items - 1):
s += ', and ' + item
else:
s += ', ' + item
return mark_safe(s)
Bạn có thể sử dụng điều này trong một mẫu django với:
{% load my_filters %}
{{ items|oxford_comma }}