Một số tích hợp sẵn để đệm danh sách trong python


110

Tôi có một danh sách có kích thước < N và tôi muốn đệm nó lên kích thước N với một giá trị.

Chắc chắn, tôi có thể sử dụng một cái gì đó như sau, nhưng tôi cảm thấy rằng có một cái gì đó tôi đã bỏ lỡ:

>>> N = 5
>>> a = [1]
>>> map(lambda x, y: y if x is None else x, a, ['']*N)
[1, '', '', '', '']

tại sao bạn muốn làm việc này? Có lẽ có một cách tốt hơn.
Katriel

Tôi sắp xếp danh sách thành một chuỗi được phân tách bằng tab với số cột cố định.
newtover

Ý bạn là bạn đang làm điều gì đó như '\ t'.join ([1,' ',' ',' ',' '])? Có thể bạn có thể cho chúng tôi biết thêm về những gì bạn dự định thực hiện, sau đó chúng tôi có thể thử đưa ra ý tưởng.
satoru

@ Satoru.Logic: vâng, print >> a_stream, '\ t'.join (the_list) là tất cả những gì tôi muốn triển khai
newtover

Câu trả lời:


165
a += [''] * (N - len(a))

hoặc nếu bạn không muốn thay đổi atại chỗ

new_a = a + [''] * (N - len(a))

bạn luôn có thể tạo một lớp con của danh sách và gọi phương thức bất cứ điều gì bạn muốn

class MyList(list):
    def ljust(self, n, fillvalue=''):
        return self + [fillvalue] * (n - len(self))

a = MyList(['1'])
b = a.ljust(5, '')

3
Ngoại hình này tốt hơn nhiều, nhưng tôi vẫn mong đợi một cái gì đó giống như một điền hoặc pad phương pháp hoặc chức năng =)
newtover

30

Tôi nghĩ rằng cách tiếp cận này là trực quan hơn và mang tính biểu tượng.

a = (a + N * [''])[:N]

Điều này khiến tôi mất nửa phút để hiểu. Câu trả lời được chấp nhận là đơn giản hơn nhiều.
Richard Möhn

3
@ RichardMöhn "pythonic" có nghĩa là "thành ngữ". Bạn sử dụng Python càng lâu, bạn sẽ thấy cú pháp này càng tự nhiên.
Nuno André

4
Tôi biết 'pythonic' có nghĩa là gì. Và tôi đã sử dụng Python liên tục từ năm 2014. Tôi vẫn không thấy câu trả lời của bạn tự nhiên.
Richard Möhn

Điều gì khiến việc xây dựng một danh sách loại bỏ trung gian trở nên khó khăn?
DylanYoung

1
@DylanYoung đây không phải là trường hợp đầu tiên khi N < len(a). Đó là trường hợp cho câu trả lời thứ hai mà bạn cung cấp.
kon psych

25

Không có chức năng tích hợp cho việc này. Nhưng bạn có thể soạn các cài sẵn cho tác vụ của mình (hoặc bất cứ thứ gì: p).

(Sửa đổi từ itertool's padnonetakecông thức nấu ăn)

from itertools import chain, repeat, islice

def pad_infinite(iterable, padding=None):
   return chain(iterable, repeat(padding))

def pad(iterable, size, padding=None):
   return islice(pad_infinite(iterable, padding), size)

Sử dụng:

>>> list(pad([1,2,3], 7, ''))
[1, 2, 3, '', '', '', '']

6

câu trả lời của gnibbler đẹp hơn, nhưng nếu bạn cần một bản nội trang, bạn có thể sử dụng itertools.izip_longest( zip_longesttrong Py3k):

itertools.izip_longest( xrange( N ), list )

điều này sẽ trả về danh sách các bộ giá trị được ( i, list[ i ] )điền vào Không có. Nếu bạn cần loại bỏ bộ đếm, hãy làm điều gì đó như:

map( itertools.itemgetter( 1 ), itertools.izip_longest( xrange( N ), list ) )

1
Tôi biết về izip_longest nhưng kết quả là mã không đẹp =)
newtover

2
Tôi tin rằng bạn có nghĩa là operator.itemgetter(). Ngoài ra các Nonegiá trị cần được thay thế bằng "".
pylang

5

Bạn cũng có thể sử dụng một trình tạo đơn giản mà không cần bất kỳ bản dựng nào. Nhưng tôi sẽ không đệm danh sách, mà để logic ứng dụng xử lý một danh sách trống.

Nhưng dù sao, trình vòng lặp không có bản dựng

def pad(iterable, padding='.', length=7):
    '''
    >>> iterable = [1,2,3]
    >>> list(pad(iterable))
    [1, 2, 3, '.', '.', '.', '.']
    '''
    for count, i in enumerate(iterable):
        yield i
    while count < length - 1:
        count += 1
        yield padding

if __name__ == '__main__':
    import doctest
    doctest.testmod()

4

Nếu bạn muốn pad bằng None thay vì '', map () thực hiện công việc:

>>> map(None,[1,2,3],xrange(7))

[(1, 0), (2, 1), (3, 2), (None, 3), (None, 4), (None, 5), (None, 6)]

>>> zip(*map(None,[1,2,3],xrange(7)))[0]

(1, 2, 3, None, None, None, None)

2
Nói thẳng ra, a + [''] * (N-len (a)) trông rõ ràng hơn nhiều. Bên cạnh đó, nó thiếu đúc vào danh sách. Nhưng dù sao cũng cảm ơn bạn.
newtover

4

more-itertoolslà một thư viện bao gồm một paddedcông cụ đặc biệt cho loại vấn đề này:

import more_itertools as mit

list(mit.padded(a, "", N))
# [1, '', '', '', '']

Ngoài ra, more_itertoolscũng triển khai các công thức của Python itertools bao gồm padnonetakenhư được đề cập bởi @kennytm, vì vậy chúng không cần phải thực hiện lại:

list(mit.take(N, mit.padnone(a)))
# [1, None, None, None, None]

Nếu bạn muốn thay thế phần Noneđệm mặc định , hãy sử dụng cách hiểu danh sách:

["" if i is None else i for i in mit.take(N, mit.padnone(a))]
# [1, '', '', '', '']

2

Để đi ra khỏi kennytm:

def pad(l, size, padding):
    return l + [padding] * abs((len(l)-size))

>>> l = [1,2,3]
>>> pad(l, 7, 0)
[1, 2, 3, 0, 0, 0, 0]


1
extra_length = desired_length - len(l)
l.extend(value for _ in range(extra_length))

Điều này tránh bất kỳ phân bổ bổ sung nào, không giống như bất kỳ giải pháp nào phụ thuộc vào việc tạo và bổ sung danh sách [value] * extra_length. Phương thức "mở rộng" lần đầu tiên gọi __length_hint__đến trình vòng lặp và mở rộng phân bổ cho lnhiều thứ đó trước khi điền nó vào từ trình vòng lặp.

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.