วิธีการสร้างรายชื่อแบบเรียบจากรายการ?


3371

ฉันสงสัยว่ามีทางลัดในการสร้างรายการอย่างง่ายจากรายการใน Python หรือไม่

ฉันสามารถทำได้ในforวง แต่อาจจะมี "หนึ่งซับ" ที่เจ๋ง ๆ ? ฉันลองด้วยreduce()แต่ฉันได้รับข้อผิดพลาด

รหัส

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)

ข้อความผิดพลาด

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'

20
มีการสนทนาในเชิงลึกเกี่ยวกับสิ่งนี้ที่นี่: rightfootin.blogspot.com/2006/09/more-on-python-flatten.htmlอภิปรายวิธีต่างๆของรายการที่ซ้อนกันแบบแบนโดยพลการ อ่านน่าสนใจ!
RichieHindle

6
บางคำตอบอื่น ๆ จะดีกว่า แต่เหตุผลของคุณล้มเหลวคือวิธีการ 'ขยาย' ส่งกลับค่าไม่มีเสมอ สำหรับรายการที่มีความยาว 2 มันจะทำงาน แต่กลับไม่มี สำหรับรายการที่ยาวกว่ามันจะใช้ 2 args แรกซึ่งส่งกลับ None จากนั้นจะดำเนินการต่อด้วย None.extend (<ARG ที่สาม>) ซึ่งทำให้เกิดข้อผิดพลาดนี้
mehtunguh

@ shawn-chin solution เป็น pythonic เพิ่มเติมที่นี่ แต่ถ้าคุณต้องการรักษาชนิดลำดับให้พูดว่าคุณมี tuple ของ tuples แทนที่จะเป็น list ของ list คุณควรใช้ลด (operator.concat, tuple_of_tuples) ใช้ operator.concat กับ tuples ดูเหมือนว่าทำงานได้เร็วกว่า chain.from_iterables พร้อมลิสต์
Meitham

คำตอบ:


4790

ได้รับรายชื่อของรายการl,

flat_list = [item for sublist in l for item in sublist]

ซึ่งหมายความว่า:

flat_list = []
for sublist in l:
    for item in sublist:
        flat_list.append(item)

เร็วกว่าทางลัดที่โพสต์ไปแล้ว ( lคือรายการที่จะเรียบ)

นี่คือฟังก์ชั่นที่เกี่ยวข้อง:

flatten = lambda l: [item for sublist in l for item in sublist]

ตามหลักฐานคุณสามารถใช้timeitโมดูลในไลบรารีมาตรฐาน:

$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop

คำอธิบาย: ทางลัดที่อิงตาม+(รวมถึงการใช้โดยนัยsum) มีความจำเป็นO(L**2)เมื่อมีรายการย่อย L - เนื่องจากรายการผลกลางจะได้รับอีกต่อไปในแต่ละขั้นตอนจะมีการจัดสรรวัตถุรายการผลลัพธ์ระดับกลางใหม่และรายการทั้งหมด ในผลลัพธ์ระดับกลางก่อนหน้าจะต้องคัดลอก (เช่นเดียวกับรายการใหม่ที่เพิ่มเข้ามาในตอนท้าย) ดังนั้นเพื่อความง่ายและโดยไม่สูญเสียความเป็นปรกติจริง ๆ สมมติว่าคุณมีรายการย่อย L ของแต่ละรายการ: รายการไอเท็มแรกของฉันจะถูกคัดลอกกลับไปกลับมา L-1 คูณสองรายการไอเท็ม L-2 ครั้งและอื่น ๆ ; จำนวนสำเนาคือผมครั้งผลรวมของ x สำหรับ x จาก 1 ถึง L I * (L**2)/2ยกเว้นคือ,

ความเข้าใจในรายการเพียงแค่สร้างหนึ่งรายการครั้งเดียวและคัดลอกแต่ละรายการผ่าน (จากที่อยู่เดิมไปยังรายการผลลัพธ์) เช่นกัน


486
ฉันลองทดสอบด้วยข้อมูลเดียวกันโดยใช้itertools.chain.from_iterable: $ python -mtimeit -s'from itertools import chain; l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'list(chain.from_iterable(l))'. มันทำงานเร็วกว่าสองเท่าเร็วพอ ๆ กับความเข้าใจในรายการซ้อนที่เร็วที่สุดของทางเลือกที่แสดงที่นี่
intuited

274
ฉันพบว่าไวยากรณ์ยากที่จะเข้าใจจนกว่าฉันจะรู้ว่าคุณสามารถคิดได้เหมือนซ้อนสำหรับลูป สำหรับรายการย่อยใน l: สำหรับรายการในรายการย่อย: รายการผลผลิต
Rob Crowell

23
@ BorisChervenkov: สังเกตว่าฉันใส่สายlist()เพื่อรับรู้ตัว iterator ลงในรายการ
สัญชาตญาณ

163
[ใบต้นไม้ในป่าใบในต้นไม้] อาจจะง่ายต่อการเข้าใจและนำไปใช้
John Mee

80
@ Joel ปัจจุบันทุกวันนี้list(itertools.chain.from_iterable(l))ดีที่สุด - ดังที่สังเกตเห็นในความคิดเห็นอื่นและคำตอบของ Shawn
Alex Martelli

1568

คุณสามารถใช้itertools.chain():

import itertools
list2d = [[1,2,3], [4,5,6], [7], [8,9]]
merged = list(itertools.chain(*list2d))

หรือคุณสามารถใช้itertools.chain.from_iterable()ซึ่งไม่ต้องการเปิดรายการด้วยตัว*ดำเนินการ :

import itertools
list2d = [[1,2,3], [4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))

13
*เป็นสิ่งที่ยุ่งยากที่ทำให้chainตรงไปตรงมาน้อยกว่าความเข้าใจรายการ คุณต้องรู้ว่าการเชื่อมโยงนั้นรวมเข้ากับ iterables ที่ส่งผ่านเป็นพารามิเตอร์เท่านั้นและ * ทำให้รายการระดับบนสุดถูกขยายเข้าไปในพารามิเตอร์ดังนั้นchainเข้าร่วมการรวม iterables ทั้งหมด แต่ไม่ได้สืบต่อไปอีก ฉันคิดว่าสิ่งนี้ทำให้เข้าใจง่ายกว่าการใช้โซ่ในกรณีนี้
Tim Dierks

52
@TimDierks: ฉันไม่แน่ใจว่า "สิ่งนี้ต้องการให้คุณเข้าใจไวยากรณ์ Python" เป็นข้อโต้แย้งกับการใช้เทคนิคที่กำหนดใน Python แน่นอนว่าการใช้งานที่ซับซ้อนอาจสร้างความสับสนได้ แต่โดยทั่วไปตัวดำเนินการ "เครื่องหมาย" จะมีประโยชน์ในหลาย ๆ สถานการณ์และสิ่งนี้ไม่ได้ใช้อย่างชัดเจนโดยเฉพาะอย่างยิ่ง การปฏิเสธคุณสมบัติด้านภาษาทั้งหมดที่ไม่จำเป็นต้องชัดเจนสำหรับผู้ใช้เริ่มต้นนั่นหมายถึงคุณกำลังผูกมือข้างหนึ่งไว้ด้านหลัง อาจทิ้งความเข้าใจในรายการด้วยเช่นกันในขณะที่คุณกำลังทำอยู่ ผู้ใช้จากพื้นหลังอื่น ๆ จะพบforวนซ้ำappendที่ชัดเจนมากขึ้น
ShadowRanger

คำตอบนี้และคำตอบอื่น ๆ ที่นี่ให้ผลไม่ถูกต้องถ้าระดับบนยังมีค่า เช่นlist = [["abc","bcd"],["cde","def"],"efg"]จะส่งผลให้["abc", "bcd", "cde", "def", "e", "f", "g"].
gouravkr

906

หมายเหตุจากผู้เขียน : นี่ไม่มีประสิทธิภาพ แต่สนุกเพราะmonoidsน่ากลัว มันไม่เหมาะสำหรับการผลิตรหัส Python

>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

นี่เป็นผลรวมขององค์ประกอบที่ผ่าน iterable ในอาร์กิวเมนต์แรกซึ่งถือว่าอาร์กิวเมนต์ที่สองเป็นค่าเริ่มต้นของผลรวม (หากไม่ได้รับ0จะถูกใช้แทนและกรณีนี้จะทำให้คุณมีข้อผิดพลาด)

เพราะคุณจะได้ข้อสรุปรายการที่ซ้อนกันคุณได้รับจริง[1,3]+[2,4]เป็นผลจากการที่จะมีค่าเท่ากับsum([[1,3],[2,4]],[])[1,3,2,4]

โปรดทราบว่าใช้งานได้กับรายการของรายการเท่านั้น สำหรับรายการของรายการคุณจะต้องมีวิธีแก้ไขปัญหาอื่น


100
มันค่อนข้างเรียบร้อยและฉลาด แต่ฉันจะไม่ใช้มันเพราะมันสับสนในการอ่าน
andrewrk

87
นี่คืออัลกอริทึมของจิตรกรShlemiel joelonsoftware.com/articles/fog0000000319.htmlซึ่งไม่มีประสิทธิภาพโดยไม่จำเป็นรวมถึงน่าเกลียดโดยไม่จำเป็น
Mike Graham

44
การดำเนินการผนวกในรายการเป็นรูปแบบ a Monoidซึ่งเป็นหนึ่งใน abstractions ที่สะดวกที่สุดสำหรับการคิดของการ+ดำเนินการในความหมายทั่วไป (ไม่ จำกัด เฉพาะตัวเลขเท่านั้น) ดังนั้นคำตอบนี้สมควรได้รับ +1 จากฉันสำหรับการรักษารายการที่ถูกต้องเป็นแบบโมโน การแสดงนั้นเกี่ยวข้องกับ ...
ulidtko

7
@ andrewrk เอาละบางคนคิดว่านี่เป็นวิธีที่สะอาดที่สุดในการทำ: youtube.com/watch?v=IOiZatlZtGUคนที่ไม่เข้าใจว่าทำไมมันถึงเจ๋งแค่รอไม่กี่สิบปีจนกระทั่งทุกคนทำแบบนี้: ) ลองใช้ภาษาการเขียนโปรแกรม (และ abstractions) ที่ถูกค้นพบและไม่ได้ประดิษฐ์คิดค้น, monoid ถูกค้นพบ
jhegedus

11
นี่เป็นวิธีที่ไม่มีประสิทธิภาพมากเพราะด้านกำลังสองของผลรวม
Jean-François Fabre

460

ฉันทดสอบวิธีแก้ปัญหาที่แนะนำส่วนใหญ่ด้วยperfplot (โครงการสัตว์เลี้ยงของฉันเป็นหลักห่อหุ้มรอบ ๆtimeit) และพบว่า

functools.reduce(operator.iconcat, a, [])

เพื่อเป็นทางออกที่เร็วที่สุดทั้งเมื่อมีรายการขนาดเล็กจำนวนมากและรายการยาวไม่กี่รายการที่ต่อกัน ( operator.iaddเร็วพอ ๆ กัน)

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่


รหัสในการทำซ้ำพล็อต:

import functools
import itertools
import numpy
import operator
import perfplot


def forfor(a):
    return [item for sublist in a for item in sublist]


def sum_brackets(a):
    return sum(a, [])


def functools_reduce(a):
    return functools.reduce(operator.concat, a)


def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def numpy_concatenate(a):
    return list(numpy.concatenate(a))


perfplot.show(
    setup=lambda n: [list(range(10))] * n,
    # setup=lambda n: [list(range(n))] * 10,
    kernels=[
        forfor,
        sum_brackets,
        functools_reduce,
        functools_reduce_iconcat,
        itertools_chain,
        numpy_flat,
        numpy_concatenate,
    ],
    n_range=[2 ** k for k in range(16)],
    xlabel="num lists (of length 10)",
    # xlabel="len lists (10 lists total)"
)

25
สำหรับรายการที่ซ้อนกันขนาดใหญ่ 'list (numpy.array (a) .flat)' นั้นเร็วที่สุดในบรรดาฟังก์ชันทั้งหมดข้างต้น
Sara

พยายามใช้ regex: 'รายการ (แผนที่ (int, re.findall (r "[\ w] +", str (a))))' ความเร็วช้าลงเล็กน้อยที่ numpy_concatenate
Justas

มีวิธีการทำแบบ 3 มิติหรือไม่? จำนวนอาร์เรย์โดยขนาดเฉลี่ยของอาร์เรย์?
Leo

ฉันรักทางออกของคุณ สั้นง่ายและมีประสิทธิภาพ :-)
ShadyMBA

181
from functools import reduce #python 3

>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(lambda x,y: x+y,l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

extend()วิธีการในตัวอย่างของคุณปรับเปลี่ยนxแทนที่จะกลับค่าที่มีประโยชน์ (ซึ่งreduce()คาดว่า)

วิธีที่เร็วกว่าในการทำreduceเวอร์ชันจะเป็น

>>> import operator
>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(operator.concat, l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

19
reduce(operator.add, l)จะเป็นวิธีที่ถูกต้องในการทำreduceเวอร์ชัน Built-in เร็วกว่า lambdas
agf

3
@agf นี่คือวิธี: * timeit.timeit('reduce(operator.add, l)', 'import operator; l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]', number=10000) 0.017956018447875977 * timeit.timeit('reduce(lambda x, y: x+y, l)', 'import operator; l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]', number=10000) 0.025218963623046875
lukmdo

8
นี่คืออัลกอริทึมของ Shlemiel the painter joelonsoftware.com/articles/fog0000000319.html
Mike Graham

2
integersนี้สามารถใช้เฉพาะสำหรับ แต่ถ้ามีรายการstringล่ะ
Freddy

3
@Freddy: operator.addฟังก์ชันใช้งานได้ดีเท่าเทียมกันสำหรับทั้งรายการจำนวนเต็มและรายการสตริง
Greg Hewgill

119

อย่าบูรณาการล้อถ้าคุณใช้Django :

>>> from django.contrib.admin.utils import flatten
>>> l = [[1,2,3], [4,5], [6]]
>>> flatten(l)
>>> [1, 2, 3, 4, 5, 6]

... นุ่น :

>>> from pandas.core.common import flatten
>>> list(flatten(l))

... Itertools :

>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))

... Matplotlib

>>> from matplotlib.cbook import flatten
>>> list(flatten(l))

... Unipath :

>>> from unipath.path import flatten
>>> list(flatten(l))

... Setuptools :

>>> from setuptools.namespaces import flatten
>>> list(flatten(l))

4
flatten = itertools.chain.from_iterableน่าจะเป็นคำตอบที่ถูกต้อง
ตุ๊กแก

3
คำตอบที่ดี! ทำงานได้กับ l = [[[1, 2, 3], [4, 5]], 5] ในกรณีของแพนด้า
Markus Dutschke

1
ฉันชอบทางออกของนุ่น ถ้าคุณมีสิ่งที่ชอบก็จะส่งผลให้เมื่อ:list_of_menuitems = [1, 2, [3, [4, 5, [6]]]] [1, 2, 3, 4, 5, 6]สิ่งที่ฉันพลาดคือระดับแบน
imjoseangel

115

นี่คือวิธีการทั่วไปที่ใช้กับตัวเลข , สตริง , ซ้อนกันรายการและผสมภาชนะบรรจุ

รหัส

#from typing import Iterable 
from collections import Iterable                            # < py38


def flatten(items):
    """Yield items from any nested iterable; see Reference."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            for sub_x in flatten(x):
                yield sub_x
        else:
            yield x

หมายเหตุ :

การสาธิต

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(flatten(lst))                                         # nested lists
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

mixed = [[1, [2]], (3, 4, {5, 6}, 7), 8, "9"]              # numbers, strs, nested & mixed
list(flatten(mixed))
# [1, 2, 3, 4, 5, 6, 7, 8, '9']

การอ้างอิง

  • วิธีการแก้ปัญหานี้ได้รับการแก้ไขจากสูตรในBeazley, D. และ B. Jones สูตร 4.14, Python Cookbook เล่มที่ 3, O'Reilly Media Inc. Sebastopol, CA: 2013
  • พบโพสต์ SOก่อนหน้าอาจเป็นการสาธิตดั้งเดิม

5
ฉันเพิ่งเขียนแบบเดียวกันมากเพราะฉันไม่เห็นวิธีแก้ปัญหาของคุณ ... นี่คือสิ่งที่ฉันมองหา "ทำให้รายการที่ซ้ำหลายรายการซ้ำซ้อน" ... (+1)
Martin Thoma

3
@MartinThoma ชื่นชมมาก FYI หากการทำซ้ำแบบซ้อนกันแบบราบเป็นเรื่องธรรมดาสำหรับคุณมีแพ็คเกจของบุคคลที่สามบางตัวที่จัดการได้ดี วิธีนี้อาจช่วยไม่ให้เกิดการพลิกโฉมพวงมาลัย ฉันได้พูดถึงmore_itertoolsคนอื่น ๆ กล่าวถึงในโพสต์นี้ ไชโย
pylang

อาจtraverseเป็นชื่อที่ดีสำหรับต้นไม้ในขณะที่ฉันจะรักษาความเป็นสากลให้น้อยลงสำหรับคำตอบนี้โดยการติดกับรายการซ้อน
Wolf

คุณสามารถตรวจสอบif hasattr(x, '__iter__')แทนการนำเข้า / ตรวจสอบกับIterableและที่จะไม่รวมสตริงเช่นกัน
Ryan Allen

รหัสข้างต้นดูเหมือนจะไม่ทำงานหากหนึ่งในรายการซ้อนกันมีรายการของสตริง [1, 2, [3, 4], [4], [], 9, 9.5, 'ssssss', ['str', 'sss', 'ss'], [3, 4, 5]] ผลลัพธ์: - [1, 2, 3, 4, 4, 9, 9.5, 'ssssss', 3, 4, 5]
sunnyX

51

หากคุณต้องการเรียบโครงสร้างข้อมูลที่คุณไม่ทราบว่ามันซ้อนกันลึกเพียงใดคุณสามารถใช้1iteration_utilities.deepflatten

>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

มันเป็นตัวกำเนิดดังนั้นคุณต้องส่งผลลัพธ์ไปที่listหรือย้ำอย่างชัดเจน


หากต้องการแบนเพียงระดับเดียวและหากรายการแต่ละรายการเป็นตัวกำหนดเองคุณสามารถใช้iteration_utilities.flattenสิ่งที่เป็นเพียงเสื้อคลุมบาง ๆitertools.chain.from_iterable:

>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

เพียงเพื่อเพิ่มการกำหนดเวลา (ตามคำตอบของ Nico Schlömerที่ไม่รวมฟังก์ชั่นที่แสดงในคำตอบนี้):

ป้อนคำอธิบายรูปภาพที่นี่

มันเป็นพล็อตการบันทึกการทำงานเพื่อรองรับค่าที่หลากหลาย สำหรับเหตุผลเชิงคุณภาพ: ต่ำกว่าดีกว่า

ผลการศึกษาพบว่าหากมี iterable iterables ภายในเพียงไม่กี่แล้วsumจะเร็วที่สุด แต่สำหรับ iterables ยาวเพียงitertools.chain.from_iterable, iteration_utilities.deepflattenหรือความเข้าใจที่ซ้อนกันมีประสิทธิภาพการทำงานที่เหมาะสมกับitertools.chain.from_iterableการเป็นที่เร็วที่สุด (เท่าที่สังเกตเห็นแล้วโดยนิโก้Schlömer)

from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
    return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
    return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
    return sum(lsts, [])

def reduce_add(lsts):
    return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
    return list(flatten(lsts))

def flatten(items):
    """Yield items from any nested iterable; see REF."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            yield from flatten(x)
        else:
            yield x

def reduce_concat(lsts):
    return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
    return list(deepflatten(lsts, depth=1))


from simple_benchmark import benchmark

b = benchmark(
    [nested_list_comprehension, itertools_chain_from_iterable, pythons_sum, reduce_add,
     pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
    arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
    argument_name='number of inner lists'
)

b.plot()

1 ข้อสงวนสิทธิ์: ฉันเป็นผู้แต่งห้องสมุดดังกล่าว


sumไม่สามารถใช้งานได้ตามลำดับโดยเริ่มต้นอีกต่อไป0ทำให้functools.reduce(operator.add, sequences)การแทนที่ (เราไม่ดีใจที่ถูกลบออกreduceจาก builtins หรือไม่) type.__add__เมื่อประเภทเป็นที่รู้จักกันมันอาจจะเร็วกว่าการใช้
Yann Vernier

@YannVernier ขอบคุณสำหรับข้อมูล ฉันคิดว่าฉันใช้มาตรฐานเหล่านี้ใน Python 3.6 และใช้งานsumได้ คุณรู้หรือไม่ว่า Python เวอร์ชันใดหยุดทำงาน?
MSeifert

ฉันค่อนข้างเข้าใจผิด 0เป็นเพียงค่าเริ่มต้นเริ่มต้นดังนั้นจึงใช้งานได้หากใช้อาร์กิวเมนต์เริ่มต้นเพื่อเริ่มต้นด้วยรายการที่ว่างเปล่า ... แต่มันยังคงสตริงกรณีพิเศษและบอกให้ฉันใช้เข้าร่วม มันดำเนินการแทนfoldl foldl1ปัญหาเดียวกันปรากฏขึ้นใน 2.7
Yann Vernier

39

ฉันเอาคำพูดของฉันกลับมา ผลรวมไม่ใช่ผู้ชนะ แม้ว่าจะเร็วกว่าเมื่อรายการมีขนาดเล็ก แต่ประสิทธิภาพลดลงอย่างมีนัยสำคัญกับรายการขนาดใหญ่

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10000'
    ).timeit(100)
2.0440959930419922

เวอร์ชั่นรวมยังคงใช้งานได้นานกว่าหนึ่งนาทีและยังไม่ได้ประมวลผล!

สำหรับรายการสื่อ:

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
20.126545906066895
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
22.242258071899414
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
16.449732065200806

ใช้รายการขนาดเล็กและ timeit: number = 1000000

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
2.4598159790039062
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.5289170742034912
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.0598428249359131

23
สำหรับรายการย่อเล็กสุดอย่างแท้จริงเช่นรายการที่มี 3 รายการย่อยอาจ - แต่เนื่องจากผลรวมของการดำเนินการไปกับ O (N ** 2) ในขณะที่รายการความเข้าใจไปกับ O (N) เพียงเพิ่มรายการเล็ก ๆ น้อย ๆ จะตรงกันข้าม - แน่นอนว่า LC จะเป็น "เร็วกว่าอนันต์" มากกว่ายอดรวมที่ขีด จำกัด เมื่อ N เติบโตขึ้น ฉันต้องรับผิดชอบในการออกแบบผลรวมและทำการติดตั้งครั้งแรกใน Python runtime และฉันก็ยังหวังว่าฉันจะพบวิธีที่จะ จำกัด มันได้อย่างมีประสิทธิภาพเพื่อรวมจำนวน (สิ่งที่ดีจริงๆ) และปิดกั้น ผู้ที่ต้องการรายการ "รวม" ;-)
Alex Martelli

38

ดูเหมือนจะมีความสับสนด้วยoperator.add! เมื่อคุณเพิ่มสองรายการเข้าด้วยกันคำที่ถูกต้องคือconcatไม่เพิ่ม operator.concatคือสิ่งที่คุณต้องการใช้

หากคุณคิดว่าการใช้งานเป็นเรื่องง่ายเหมือนนี้ ::

>>> from functools import reduce
>>> list2d = ((1, 2, 3), (4, 5, 6), (7,), (8, 9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)

คุณจะเห็นการลดลงของลำดับลำดับดังนั้นเมื่อคุณจัดหา tuple คุณจะได้รับ tuple กลับมา ลองทำรายการ ::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

อ๊ะคุณกลับรายการแล้ว

วิธีการเกี่ยวกับประสิทธิภาพ ::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop

from_iterableค่อนข้างเร็ว! concatแต่มันก็เปรียบเทียบเพื่อลดไม่มี

>>> list2d = ((1, 2, 3),(4, 5, 6), (7,), (8, 9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop

1
อืมจะเป็นตัวอย่างที่สองที่เป็นธรรมควรเป็น list (หรือ tuple แรก?)
Mr_and_Mrs_D

2
การใช้อินพุตขนาดเล็กเช่นนั้นไม่ได้เป็นการเปรียบเทียบที่ยุติธรรม 1000 ลำดับของความยาว 1000 ฉันได้รับ 0.037 วินาทีlist(chain.from_iterable(...))และ 2.5 reduce(concat, ...)วินาที ปัญหาคือreduce(concat, ...)มีรันไทม์กำลังสองในขณะที่chainเป็นเส้นตรง
kaya3

33

เหตุใดคุณใช้ส่วนขยาย

reduce(lambda x, y: x+y, l)

ควรทำงานได้ดี


7
สำหรับ python3from functools import reduce
andorov

ขออภัยที่ช้ามากดูคำตอบที่เหลือ
Mr_and_Mrs_D

นี่เป็นวิธีที่ง่ายที่สุดที่จะเข้าใจสั้น ๆ แต่วิธีแก้ปัญหาที่ใช้กับ Python 2 และ 3 ฉันรู้ว่า Python folks จำนวนมากอยู่ในการประมวลผลข้อมูลซึ่งมีข้อมูลจำนวนมากที่ต้องประมวลผลและสนใจความเร็วมาก แต่เมื่อคุณ กำลังเขียนเชลล์สคริปต์และมีองค์ประกอบเพียงไม่กี่โหลในรายการย่อยไม่กี่รายการดังนั้นจึงสมบูรณ์แบบ
Asfand Qazi

27

พิจารณาติดตั้งmore_itertoolsแพ็กเกจ

> pip install more_itertools

มันมาพร้อมกับการใช้งานสำหรับflatten( แหล่งที่มาจากสูตร itertools ):

import more_itertools


lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.flatten(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

ในเวอร์ชัน 2.4 คุณสามารถแบนตัวควบคุม iterables แบบซ้อนที่มีความซับซ้อนมากขึ้นmore_itertools.collapse( แหล่งที่มาสนับสนุนโดย abarnet)

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.collapse(lst)) 
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

lst = [[1, 2, 3], [[4, 5, 6]], [[[7]]], 8, 9]              # complex nesting
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

จริง นี่ควรเป็นคำตอบที่ได้รับการยอมรับ
brunetton

หากคุณสามารถเพิ่มแพ็คเกจให้กับโครงการของคุณได้คำตอบนี้ดีที่สุด
viddik13

22

เหตุผลที่ฟังก์ชั่นของคุณใช้งานไม่ได้เพราะส่วนขยายขยายอาร์เรย์เข้าที่และไม่ส่งคืน คุณยังสามารถคืนค่า x จากแลมบ์ดาโดยใช้บางสิ่งเช่นนี้:

reduce(lambda x,y: x.extend(y) or x, l)

หมายเหตุ: ส่วนขยายมีประสิทธิภาพมากกว่า + ในรายการ


7
extendถูกนำมาใช้ที่ดีกว่าnewlist = [], extend = newlist.extend, for sublist in l: extend(l)ในขณะที่มันหลีกเลี่ยง (ค่อนข้างใหญ่) ค่าใช้จ่ายของlambdaการค้นหาแอตทริบิวต์บนและx or
agf

สำหรับ python 3 เพิ่มfrom functools import reduce
Markus Dutschke

17
def flatten(l, a):
    for i in l:
        if isinstance(i, list):
            flatten(i, a)
        else:
            a.append(i)
    return a

print(flatten([[[1, [1,1, [3, [4,5,]]]], 2, 3], [4, 5],6], []))

# [1, 1, 1, 3, 4, 5, 2, 3, 4, 5, 6]

def flatten(l, a=None): if a is None: a = [][... ]
Poik

16

เวอร์ชันเรียกซ้ำ

x = [1,2,[3,4],[5,[6,[7]]],8,9,[10]]

def flatten_list(k):
    result = list()
    for i in k:
        if isinstance(i,list):

            #The isinstance() function checks if the object (first argument) is an 
            #instance or subclass of classinfo class (second argument)

            result.extend(flatten_list(i)) #Recursive call
        else:
            result.append(i)
    return result

flatten_list(x)
#result = [1,2,3,4,5,6,7,8,9,10]

1
ดีไม่จำเป็นต้องนำเข้าและเป็นที่ชัดเจนเป็นสิ่งที่มันทำ ... แฟบรายการระยะเวลา :)
Goran บี

1
ยอดเยี่ยมเพียง!
Sachin Sharma

15

matplotlib.cbook.flatten() จะใช้งานได้กับรายการที่ซ้อนกันแม้ว่าจะซ้อนอยู่ลึกกว่าตัวอย่าง

import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print list(matplotlib.cbook.flatten(l2))

ผลลัพธ์:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

นี่คือ 18x เร็วกว่าขีดล่าง. _. แผ่:

Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636

14

คำตอบที่ยอมรับนั้นใช้ไม่ได้กับฉันเมื่อจัดการกับรายการข้อความที่มีความยาวผันแปรได้ นี่คือวิธีการสำรองที่ใช้งานได้สำหรับฉัน

l = ['aaa', 'bb', 'cccccc', ['xx', 'yyyyyyy']]

คำตอบที่ยอมรับซึ่งไม่ได้ผล:

flat_list = [item for sublist in l for item in sublist]
print(flat_list)
['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'xx', 'yyyyyyy']

โซลูชั่นใหม่ที่นำเสนอไม่ทำงานสำหรับฉัน:

flat_list = []
_ = [flat_list.extend(item) if isinstance(item, list) else flat_list.append(item) for item in l if item]
print(flat_list)
['aaa', 'bb', 'cccccc', 'xx', 'yyyyyyy']

13

คุณลักษณะที่ไม่ดีของฟังก์ชั่นของ Anil ด้านบนคือต้องการให้ผู้ใช้ระบุอาร์กิวเมนต์ที่สองด้วยตนเองเป็นรายการว่าง[]เสมอ นี่ควรเป็นค่าเริ่มต้นแทน เนื่องจากวิธีการทำงานของวัตถุ Python จึงควรตั้งค่าเหล่านี้ไว้ภายในฟังก์ชันไม่ใช่ในอาร์กิวเมนต์

นี่คือฟังก์ชั่นการทำงาน:

def list_flatten(l, a=None):
    #check a
    if a is None:
        #initialize with empty list
        a = []

    for i in l:
        if isinstance(i, list):
            list_flatten(i, a)
        else:
            a.append(i)
    return a

การทดสอบ:

In [2]: lst = [1, 2, [3], [[4]],[5,[6]]]

In [3]: lst
Out[3]: [1, 2, [3], [[4]], [5, [6]]]

In [11]: list_flatten(lst)
Out[11]: [1, 2, 3, 4, 5, 6]

13

ต่อไปนี้ดูเหมือนง่ายที่สุดสำหรับฉัน:

>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print (np.concatenate(l))
[1 2 3 4 5 6 7 8 9]

ไม่ทำงานกับรายการที่มีมิติข้อมูลต่างกัน -1
nurub

10

ท่านสามารถใช้แฟลตของ NumPy :

import numpy as np
list(np.array(l).flat)

แก้ไข 11/02/2016: ใช้ได้เฉพาะเมื่อรายการย่อยมีขนาดเท่ากัน


นั่นจะเป็นทางออกที่ดีที่สุดเหรอ?
RetroCode

6

คุณสามารถใช้จำนวน:
flat_list = list(np.concatenate(list_of_list))


ใช้ได้กับตัวเลขสตริงและรายการผสมเช่นกัน
Nitin

2
ล้มเหลวสำหรับข้อมูลที่ซ้อนกันไม่สม่ำเสมอเช่น[1, 2, [3], [[4]], [5, [6]]]
EL_DON

5

หากคุณยินดีที่จะละทิ้งความเร็วเล็กน้อยเพื่อให้ดูสะอาดตาคุณสามารถใช้numpy.concatenate().tolist()หรือnumpy.concatenate().ravel().tolist():

import numpy

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99

%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop

%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop

%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop

คุณสามารถหาข้อมูลเพิ่มเติมได้ที่นี่ในเอกสารnumpy.concatenateและnumpy.ravel


1
ไม่ทำงานกับรายการที่ซ้อนไม่สม่ำเสมอเช่น[1, 2, [3], [[4]], [5, [6]]]
EL_DON

5

ฉันพบวิธีแก้ปัญหาที่เร็วที่สุด (สำหรับรายการขนาดใหญ่แล้ว):

import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()

ทำ! แน่นอนว่าคุณสามารถเปลี่ยนกลับเป็นรายการได้โดยดำเนินการรายการ (l)


1
นี่เป็นความผิดแบนจะลดขนาดของอาร์เรย์ที่สองเป็นหนึ่ง แต่ไม่เชื่อมต่อรายการภายในเป็นหนึ่ง
Ando Jurai

5

รหัสง่าย ๆ สำหรับunderscore.pyแฟนแพ็คเกจ

from underscore import _
_.flatten([[1, 2, 3], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

มันแก้ปัญหาแผ่แบนทั้งหมด (ไม่มีรายการในรายการหรือการซ้อนที่ซับซ้อน)

from underscore import _
# 1 is none list item
# [2, [3]] is complex nesting
_.flatten([1, [2, [3]], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

คุณสามารถติดตั้งunderscore.pyด้วย pip

pip install underscore.py

ในทำนองเดียวกันคุณสามารถใช้pydash ฉันพบว่ารุ่นนี้สามารถอ่านได้มากกว่าความเข้าใจในรายการหรือคำตอบอื่น ๆ
gliemezis

2
นี่ช้าสุด ๆ
Nico Schlömer

2
ทำไมจึงมีโมดูลชื่อ _ ดูเหมือนว่าจะเป็นชื่อที่ไม่ดี ดูstackoverflow.com/a/5893946/6605826
EL_DON

2
@EL_DON: จาก underscore.py readme page "Underscore.py เป็นพอร์ต python ของไลบรารี javascript ที่ยอดเยี่ยม underscore.js" ฉันคิดว่ามันเป็นเหตุผลสำหรับชื่อนี้ และใช่มันไม่ใช่ชื่อที่ดีสำหรับงูหลาม
Vu Anh

5
def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])

ล้มเหลวสำหรับ python2.7 สำหรับรายการซ้อนตัวอย่างในคำถาม:[[1, 2, 3], [4, 5, 6], [7], [8, 9]]
EL_DON

@EL_DON ทดสอบกับ python 2.7.5 มันใช้งานได้ดี
englealuze

5

หมายเหตุ : ด้านล่างนี้นำไปใช้กับงูหลาม 3.3 yield_fromหรือสูงกว่าเพราะมันใช้ sixเป็นแพ็คเกจของบุคคลที่สามแม้ว่าจะมีเสถียรภาพ sys.versionหรือคุณสามารถใช้


ในกรณีที่มีทั้งหมดของโซลูชั่นที่นี่เป็นสิ่งที่ดีรวมทั้งความเข้าใจและรายการobj = [[1, 2,], [3, 4], [5, 6]]itertools.chain.from_iterable

อย่างไรก็ตามให้พิจารณากรณีที่ซับซ้อนเล็กน้อยนี้:

>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]

มีปัญหาหลายอย่างที่นี่:

  • องค์ประกอบหนึ่ง6, เป็นเพียงสเกลาร์; ไม่สามารถทำซ้ำได้ดังนั้นเส้นทางด้านบนจะล้มเหลวที่นี่
  • องค์ประกอบหนึ่ง'abc', เป็นเทคนิค iterable (ทุกstrs) อย่างไรก็ตามการอ่านระหว่างบรรทัดเล็กน้อยคุณไม่ต้องการที่จะปฏิบัติกับมันเช่น - คุณต้องการที่จะปฏิบัติกับมันเป็นองค์ประกอบเดียว
  • องค์ประกอบสุดท้าย[8, [9, 10]]คือตัวเอง iterable ซ้อนกัน ความเข้าใจพื้นฐานของรายการและchain.from_iterableเพียงดึง "ลง 1 ระดับ" เท่านั้น

คุณสามารถแก้ไขได้ดังนี้:

>>> from collections import Iterable
>>> from six import string_types

>>> def flatten(obj):
...     for i in obj:
...         if isinstance(i, Iterable) and not isinstance(i, string_types):
...             yield from flatten(i)
...         else:
...             yield i


>>> list(flatten(obj))
[1, 2, 3, 4, 5, 6, 'abc', 7, 8, 9, 10]

ที่นี่คุณตรวจสอบว่าองค์ประกอบย่อย (1) สามารถทำซ้ำได้ด้วยIterableABC จากitertoolsแต่ยังต้องการให้แน่ใจว่า (2) องค์ประกอบนั้นไม่ใช่ "เหมือนสตริง"


1
หากคุณยังคงสนใจในความเข้ากันได้ของ Python 2 ให้เปลี่ยนyield fromเป็นforลูปเช่นfor x in flatten(i): yield x
pylang

5
flat_list = []
for i in list_of_list:
    flat_list+=i

จรรยาบรรณนี้ยังใช้งานได้ดีเพราะมันขยายรายการไปเรื่อย ๆ แม้ว่ามันจะคล้ายกันมาก แต่มีเพียงหนึ่งวงเท่านั้น ดังนั้นจึงมีความซับซ้อนน้อยกว่าการเพิ่ม 2 สำหรับลูป


5
from nltk import flatten

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
flatten(l)

ข้อดีของการแก้ปัญหานี้เหนือคนอื่นส่วนใหญ่ที่นี่คือถ้าคุณมีรายการเช่น:

l = [1, [2, 3], [4, 5, 6], [7], [8, 9]]

ในขณะที่โซลูชันอื่น ๆ ส่วนใหญ่มีข้อผิดพลาดโซลูชันนี้จะจัดการกับพวกเขา


คำถามระบุ "รายการของรายการ" แต่รายการตัวอย่างของคุณมีรายการที่ไม่ใช่รายการ โซลูชันอื่น ๆ ส่วนใหญ่ติดกับคำถามเดิม โซลูชันของคุณแก้ปัญหาที่กว้างขึ้น แต่ยังต้องใช้แพ็คเกจ Python ที่ไม่ใช่ฐาน (nltk) ซึ่งจะต้องติดตั้งก่อน
simonobo

4

นี่อาจไม่ใช่วิธีที่มีประสิทธิภาพที่สุด แต่ฉันคิดว่าจะใช้หนึ่งซับ (จริง ๆ แล้วเป็นสองซับ) ทั้งสองเวอร์ชันจะทำงานกับรายการที่ซ้อนกันตามลำดับชั้นโดยพลการและใช้ประโยชน์จากคุณลักษณะทางภาษา (Python3.5) และการเรียกซ้ำ

def make_list_flat (l):
    flist = []
    flist.extend ([l]) if (type (l) is not list) else [flist.extend (make_list_flat (e)) for e in l]
    return flist

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = make_list_flat(a)
print (flist)

ผลลัพธ์คือ

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

วิธีนี้ใช้ได้ผลในเชิงลึกก่อน การเรียกซ้ำลงไปจนกระทั่งพบองค์ประกอบที่ไม่ใช่รายการจากนั้นขยายตัวแปรโลคัลflistและจากนั้นย้อนกลับไปยังพาเรนต์ เมื่อใดก็ตามที่flistถูกส่งคืนจะถูกขยายไปยังผู้ปกครองflistในรายการความเข้าใจ ดังนั้นที่รูทรายการแฟล็กจะถูกส่งคืน

รายการด้านบนสร้างรายการท้องถิ่นหลายรายการและส่งคืนรายการที่ใช้เพื่อขยายรายการผู้ปกครอง ฉันคิดว่าวิธีการสำหรับสิ่งนี้อาจเป็นการสร้างภาพลักษณ์ที่เยือกเย็นflistดังด้านล่าง

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = []
def make_list_flat (l):
    flist.extend ([l]) if (type (l) is not list) else [make_list_flat (e) for e in l]

make_list_flat(a)
print (flist)

ผลลัพธ์เป็นอีกครั้ง

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

แม้ว่าฉันไม่แน่ใจในเวลานี้เกี่ยวกับประสิทธิภาพ


ทำไมต้องขยาย ([l]) แทนการต่อท้าย (l)
Maciek

3

อีกวิธีที่ผิดปกติที่ใช้กับรายการจำนวนเต็มและเป็นเนื้อเดียวกัน:

from typing import List


def flatten(l: list) -> List[int]:
    """Flatten an arbitrary deep nested list of lists of integers.

    Examples:
        >>> flatten([1, 2, [1, [10]]])
        [1, 2, 1, 10]

    Args:
        l: Union[l, Union[int, List[int]]

    Returns:
        Flatted list of integer
    """
    return [int(i.strip('[ ]')) for i in str(l).split(',')]

นั่นเป็นเพียงความซับซ้อนและช้าลงเล็กน้อยจากสิ่งที่ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000โพสต์ไปแล้วก่อนหน้านี้ ฉันอัตชีวประวัติข้อเสนอของเขาเมื่อวานนี้ดังนั้นวิธีการนี้ดูเหมือนว่าค่อนข้างเป็นที่นิยมในวันนี้;)
Darkonaut

ไม่มาก: wierd_list = [[1, 2, 3], [4, 5, 6], [7], [8, 9], 10]>>nice_list=[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0]
เมื่อ

รหัสของฉันเป็นหนึ่งในสายการบินจะเป็น: flat_list = [int(e.replace('[','').replace(']','')) for e in str(deep_list).split(',')]
tharndt

1
คุณถูก +1 จริง ๆ ข้อเสนอของᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000จะไม่ทำงานกับตัวเลขหลายหลักฉันไม่ได้ทดสอบมาก่อนแม้ว่ามันจะชัดเจน [int(e.strip('[ ]')) for e in str(deep_list).split(',')]คุณสามารถลดความซับซ้อนของรหัสและการเขียนของคุณ แต่ฉันขอแนะนำให้ติดกับข้อเสนอของ Deleet สำหรับกรณีการใช้งานจริง มันไม่มีการแปลงประเภทแฮ็คมันเร็วและหลากหลายมากขึ้นเพราะมันยังจัดการรายการที่มีหลากหลายประเภทตามธรรมชาติ
Darkonaut

2
น่าเสียดายที่ไม่มี แต่ฉันเห็นรหัสนี้เมื่อเร็ว ๆ นี้ที่นี่: Python Practice Book 6.1.2
tharndt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.