2012-04-05 42 views
7

Có cách tháo gỡ các phần tử trống rỗng trong danh sách theo kiểu pythonian thanh lịch không. Một loại list.rstrip (Không). Vì vậy,xoá các phần tử rỗng có đuôi trong Python

[1, 2, 3, None, 4, None, None] 

nên kết quả trong

[1, 2, 3, None, 4] 

Tôi đoán đây có thể được khái quát hóa để loại bỏ các yếu tố dấu của bất kỳ giá trị cụ thể.


CẬP NHẬT: Tôi nên đã xác định rằng tôi muốn điều này được thực hiện như một dòng duy nhất (có thể đọc được) biểu

+2

Có gì sai với vòng lặp? Không phải mọi lớp lót đều có thể đọc được. Bỏ phiếu xuống vì bản cập nhật của bạn – Abhijit

+2

Đây là dòng đơn (có thể đọc được): 'strip_trailing_empty_elements (the_list)'. Tôi đề nghị bạn sử dụng một trong những câu trả lời bạn đã đưa ra để định nghĩa 'strip_trailing_empty_elements()', – Duncan

+1

Như tôi đã nói, tôi muốn một lớp "có thể đọc" (luôn luôn dễ đọc hơn vòng lặp). Nếu bạn không nghĩ rằng có bất kỳ như thế, thì đó là câu trả lời cho câu hỏi của tôi. Vì vậy, tại sao downvote? –

Trả lời

14

Sửa: Để sử dụng pop() thay vì cắt danh sách, như bình luận có đề xuất chính xác.

Tôi không biết nếu có một cách pythonic hơn, nhưng công trình này:

my_list = [1, 2, 3, None, 4, None, None] 
while not my_list[-1]: 
    my_list.pop() 
print my_list 
>>>[1, 2, 3, None, 4] 

Sửa: Như @DSM chỉ ra, nếu bạn chỉ muốn thoát khỏi None giá trị, và để lại số không hoặc giá trị falsy khác, bạn có thể làm:

while my_list and my_list[-1] is None: 
    my_list.pop() 
+1

Điều này cũng sẽ xóa các số 0 ở cuối (và bất kỳ điều gì khác không đúng.) – DSM

+2

Điều này sẽ tạo các bản sao không cần thiết tại mỗi lần lặp – Abhijit

+0

@DSM Khá chính xác. Đã chỉnh sửa câu trả lời để tính đến điều đó. – alan

7

sau đây kiểm tra một cách rõ ràng cho None yếu tố:

while l and l[-1] is None: 
    l.pop() 

Nó có thể được khái quát như sau:

f = lambda x: x is None 
while l and f(l[-1]): 
    l.pop() 

Bây giờ bạn có thể xác định các chức năng khác nhau cho f để kiểm tra các điều kiện khác.

+0

xin vui lòng xem bản cập nhật của tôi –

+2

Giải pháp tốt, nhưng nó ném một ngoại lệ khi một danh sách chỉ chứa Nones. Có lẽ 'trong khi l và f (l [-1])' – georg

+0

@ thg435: vâng, bạn nói đúng. Tôi đã thêm sửa đổi của bạn vào bài đăng, cảm ơn. –

2

Hãy thử điều này

>>> x=[1, 2, 3, None, 4, None, None] 
>>> while x[-1] is None: 
    x.pop() 
+0

vui lòng xem cập nhật của tôi –

+0

câu trả lời của bạn giống như câu trả lời của người khác, bạn có thể thêm phiếu bầu vào câu trả lời của mình thay vì đưa ra câu trả lời mới. – pylover

+2

@pylover: câu trả lời của alan tạo ra các bản sao không cần thiết. Anh ấy nên đã sử dụng pop để thay thế. – Abhijit

1

Đối với một giải pháp một dòng:

In [30]: from itertools import dropwhile 

In [31]: list(reversed(tuple(dropwhile(lambda x: x is None, reversed([1, 2, 3, None, 4, None, None]))))) 
Out[31]: [1, 2, 3, None, 4] 

Nếu bạn muốn sử dụng nó, đây là một định nghĩa theo kiểu point-miễn phí:

In [36]: from functional import compose, partial 

In [37]: varargs = lambda *args: args 

In [38]: compose_mult = compose(partial(reduce, compose),varargs) # compose which takes variable number of arguments. Innermost function to the right. 

In [39]: compose_mult(list, reversed, tuple, partial(dropwhile, lambda x: x is None), reversed)([1, 2, 3, None, 4, None, None]) 
Out[39]: [1, 2, 3, None, 4] 
+0

Nó hoạt động nhưng nó hy sinh khả năng đọc quá nhiều trong quan điểm của tôi. –

+0

@SimeonVisser Đó là một vấn đề của ý kiến, nhưng có, tôi không điên về sự cần thiết phải buộc một tuple ở giữa. – Marcin

3
def remove_trailing(l, remove_value=None): 
     i = len(l) 
     while i>0 and l[i-1] == remove_value: 
      i -= 1 
     return l[:i] 
+0

Đây là câu trả lời hay nhất cho đến nay. Một biến thể khác sẽ là một phép gán slice tại chỗ thay vì trả về slice để duy trì sự tách biệt lệnh/truy vấn.Nếu bạn vào đó. Đây là một kiểu dáng đẹp. – aaronasterling

+0

@aaronasterling Tôi thích giải pháp này. Tôi đang cố gắng tìm hiểu thêm về phong cách chức năng. Ý bạn là gì bởi __in-place slice assignment__. Chỉ cần gán slice trở lại tham số 'l'? Và không trả lại nó? (Chắc chắn không phải) – alan

+0

@alan, thay vì 'return l [: i]', nó sẽ là 'l [:] = l [: i]'. Điều đó làm cho nó một lệnh ở chỗ nó sẽ thay đổi trạng thái 'l'. Tôi đã tắt cơ sở ở chỗ nó hiện là một truy vấn (trả về dữ liệu và không thay đổi trạng thái) để nó duy trì tách truy vấn lệnh. Tôi đã hình dung sử dụng nó như 'l = remove_trailing (l)' và _that_ sẽ vi phạm phân tách CQ, _imo_. Có lẽ tôi đang ở mức quá mức ở đây. – aaronasterling

0

Dưới đây là một lớp lót khác:

>>> l = [1, 2, 3, None, 4, None, None] 
>>> [l[i] for i in range(len("".join(map(lambda x: {None: " "}.get(x, "_"), l)).rstrip()))] 
[1, 2, 3, None, 4] 

Những điều này rất thú vị!

EDIT

Tôi chỉ nhận ra rằng danh sách hiểu là hoàn toàn không cần thiết. Cắt chỉ hoạt động tốt:

>>> l[:len("".join(map(lambda x: {None: " "}.get(x, "_"), l)).rstrip())] 
+0

Và nó sử dụng 'rstrip()', mặc dù theo một cách rất vòng xoay. –

1

Nếu bạn thực sự cần thỏa hiệp khả năng đọc ở đây là những gì tôi muốn làm.

>>> from itertools import takewhile 
>>> l=[1,2,3,None,4,5,None,None] 
>>> l[:-len(list(takewhile(lambda x: x==None, reversed(l))))] 
[1,2,3,None,4,5] 
+0

Nó xuất hiện từ đầu ra của bạn mà điều này đạt được không có gì. – Marcin

+0

Tôi sao chép dán dòng sai, thay vào đó nó đạt được kết quả chính xác và tôi đặt cược nhanh hơn nhiều giải pháp khác – luke14free

0

Điều gì về đệ quy + cắt?

>>> rstrip = lambda x, elts=(None,): rstrip(x[:-1], elts) if x and x[-1] in elts else x 
>>> rstrip([1, 2, 3, None]) 
[1, 2, 3] 
>>> rstrip([1, 2, 3, None], (None, 3)) 
[1, 2] 

Lưu ý: Tôi giả định rằng bạn đang không tìm kiếm các giải pháp tính toán hiệu quả nhất ở đây ...

0

gì về:

[a[i] for i in range(len(a)) if a[i:] != [None] * (len(a) - i) ] 
1

tôi không bao giờ chấp nhận một câu trả lời vì tôi đã không thực sự hài lòng với các giải pháp được cung cấp. Đây là một giải pháp (1 dòng và không có thư viện phụ thuộc) mà Tôi không hoàn toàn hài lòng với một trong hai:

a = [1, 2, None, 3, None, None] 
reduce(lambda l, e: [e]+l if l or e is not None else [], reversed(a), []) 
+0

Sẽ rất tuyệt nếu https://docs.python.org/3.6/library/stdtypes.html#str.rstrip tồn tại cho danh sách. Nhưng kể từ khi nó không, vòng lặp pop hai dòng của alan làm việc cho tôi. – Dave

0

Dự án more_itertools thực hiện rstrip cho bất kỳ iterable:

iterable = [1, 2, 3, None, 4, None, None] 
list(mit.rstrip(iterable, lambda x: x in {None})) 
# [1, 2, 3, None, 4] 

more_itertools.rstrip chấp nhận một iterable và vị ngữ . Xem chi tiết source code.

Các vấn đề liên quan