Câu hỏi liên quan

Python nhóm yếu tố trong một danh sách trong việc tăng kích thước


0 Phiếu
Đã hỏi 22/5/2016 bởi pbz_so (800 điểm) 1 Phản ánh
my_list = [my_list[int((i**2 + i)/2):int((i**2 + 3*i + 3)/2)] for i in range(int((-1 + (1 + 8*len(my_list))**0.5)/2))]
có một neater giải pháp là để nhóm các yếu tố của một danh sách vào nhóm tăng kích thước so với điều này? Ví dụ:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] --> [[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]
[1, 2, 3, 4] --> [[1], [2, 3]]
[1, 2, 3, 4, 5, 6] --> [[1], [2, 3], [4, 5, 6]]
EDIT ở đây là các kết quả từ timeit:
from timeit import Timer
from itertools import count
def martijn(it):
    it = iter(it)
    return list([next(it) for _ in range(s)] for s in count(1))
def mathematical(it):
    upper_bound = int(((1 + 8*len(it))**0.5 + 1)//2)
    return [it[i*(i-1)//2:i*(i+1)//2] for i in range(1, upper_bound)]
def time(test, n):
    a = Timer(lambda: martijn(test)).timeit(n)
    b = Timer(lambda: mathematical(test)).timeit(n)
    return round(a, 3), round(b, 3)
>>> for i in range(8):
        loops = 10**max(0, (6-i))
        print(time([n for n in range(10**i)], loops), loops)
(6.753, 4.416) 1000000
(1.166, 0.629) 100000
(0.366, 0.123) 10000
(0.217, 0.036) 1000
(0.164, 0.017) 100
(0.157, 0.017) 10
(0.167, 0.021) 1
(1.749, 0.251) 1
>>> for i in range(8):
        loops = 10**max(0, (6-i))
        print(time(range(10**i), loops), loops)
(6.721, 4.779) 1000000
(1.184, 0.796) 100000
(0.367, 0.173) 10000
(0.218, 0.051) 1000
(0.202, 0.015) 100
(0.178, 0.005) 10
(0.207, 0.002) 1
(1.872, 0.005) 1

3 Câu trả lời

0 Phiếu
Đã trả lời 03/6/2016 bởi Vff_The (190 điểm)
Bằng cách sử dụng một biểu thức generator :
from itertools import count
try:
    _range = xrange
except NameError:
    # Python 3
    _range = range

def incremental_window(it):
    """Produce monotonically increasing windows on an iterable.
    Only complete windows are yielded, if the last elements do not form
    a complete window they are ignored.
    incremental_window('ABCDEF') -> ['A'], ['B', 'C'], ['D', 'E', 'F']
    incremental_window('ABCDE') -> ['A'], ['B', 'C']
    """
    it = iter(it)
    return ([next(it) for _ in _range(s)] for s in count(1))
Demo:
>>> list(incremental_window([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]))
[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]
>>> list(incremental_window([1, 2, 3, 4]))
[[1], [2, 3]]
>>> list(incremental_window([1, 2, 3, 4, 5, 6]))
[[1], [2, 3], [4, 5, 6]]
đây là một generator sẽ làm việc với bất kỳ iterables endless iterable, trong đó:
>>> from itertools import count
>>> for window in incremental_window(count()):
...     print window
...     if 25 in window:
...         break
... 
[0]
[1, 2]
[3, 4, 5]
[6, 7, 8, 9]
[10, 11, 12, 13, 14]
[15, 16, 17, 18, 19, 20]
[21, 22, 23, 24, 25, 26, 27]
bạn có thể làm cho rằng một one-liner với gian lận một chút 'inline' iter() cuộc gọi trên đối tượng danh sách của bạn:
list([next(it) for _ in _range(s)] for it in (iter(my_list),) for s in count(1))
Đã bình luận 04/6/2016 bởi Vogts_Me (240 điểm)
Các mô hình mà bạn đang cố gắng để đạt được ở đây là gì? Mỗi sublist có nên 1 element so với sublist trước đó?
0 Phiếu
Đã trả lời 03/6/2016 bởi Bolk_respons (190 điểm)
Vâng, đó là câu trả lời đơn giản.
>>> test = [1, 2, 3, 4, 5, 6, 7]
>>> bound = int((-1 + (1 + 8 * len(test)) ** 0.5) / 2)
>>> res = [test[(i + 1) * i // 2 : (i + 1) * (i + 2) // 2] for i in xrange(bound)]
>>> res
[[1], [2, 3], [4, 5, 6]]
bởi vì kích thước của mỗi miếng là một dãy số học. Và phương trình để tính toán tổng số học trình tự được biết đến. Vì vậy, chúng tôi chỉ đơn giản là có thể tính toán các chỉ số bắt đầu và kết thúc của mỗi lát trực tiếp với phương trình đó.
Đã bình luận 04/6/2016 bởi Yuste (610 điểm)
Chúa ơi. Vì lợi ích của triết học Python's, tôi chân thành hy vọng như vậy.
0 Phiếu
Đã trả lời 03/6/2016 bởi Are_gilb (140 điểm)
(n * (n - 1) / 2, n * (n + 1) / 2)
này cung cấp cho bạn, theo chỉ số Gauss, bắt đầu và kết thúc của element thứ n của bạn danh sách mới. Do đó
my_list[n * (n - 1) / 2 : n * (n + 1) / 2]
là element thứ n của danh sách, và với một chút cùn lọc:
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[my_list[n * (n - 1) / 2: n * (n + 1)/ 2] for n in range(1, len(my_list)) if n * (n + 1)/ 2 <= len(my_list)]
# [[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]
A loop thích hợp với một break thực tế có lẽ sẽ tốt hơn, mặc dù

chỉnh sửa

bây giờ mà tôi biết về làm thế nào StopIteration bị bắt bởi list (cảm ơn bạn Martjin), một điều kiện đơn giản đóng cửa có thể được thực hiện bằng cách sử dụng:
list(my_list[n * (n - 1) // 2: n * (n + 1) // 2] for n in count(1) if iter(my_list[n * (n + 1)/ 2:]).next() > -1)
cung cấp -1 là thấp hơn so với bất kỳ mục nào trong danh sách của bạn. (Và các đơn vị sàn cho integer gõ bằng python 3.)

ToughDev Q&A là gì?

Trang web hỏi đáp cho các bạn đam mê lập trình, phát triển phần mềm và các vấn đề kỹ thuật khác. Với sự giúp đỡ của bạn, chúng tôi hy vọng sẽ xây dựng thành công một thư viện đầy đủ các câu hỏi và trả lời về tất cả các vấn đề có liên quan đến lập trình!







...