ฉันจะต่อสองรายการใน Python ได้อย่างไร
ตัวอย่าง:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
ผลลัพธ์ที่คาดหวัง:
>>> joinedlist
[1, 2, 3, 4, 5, 6]
[1,2,5] and [2,4,5,6]
? คุณต้องการให้มีรายการที่ซ้ำกันรวมแยกออกหรือไม่สนใจหรือไม่
ฉันจะต่อสองรายการใน Python ได้อย่างไร
ตัวอย่าง:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
ผลลัพธ์ที่คาดหวัง:
>>> joinedlist
[1, 2, 3, 4, 5, 6]
[1,2,5] and [2,4,5,6]
? คุณต้องการให้มีรายการที่ซ้ำกันรวมแยกออกหรือไม่สนใจหรือไม่
คำตอบ:
คุณสามารถใช้+
โอเปอเรเตอร์เพื่อรวม:
listone = [1,2,3]
listtwo = [4,5,6]
joinedlist = listone + listtwo
เอาท์พุท:
>>> joinedlist
[1,2,3,4,5,6]
listone += listtwo
ส่งผลให้listone == [1, 2, 3, 4, 5, 6]
list3 = listone
listone+=listtwo
list3 ก็เปลี่ยนไปเช่นกัน?
นอกจากนี้ยังเป็นไปได้ที่จะสร้างเครื่องกำเนิดไฟฟ้าที่เพียง iterates itertools.chain()
กว่ารายการในทั้งสองรายการโดยใช้ สิ่งนี้อนุญาตให้คุณโยงรายชื่อ (หรือทำซ้ำได้) เข้าด้วยกันเพื่อการประมวลผลโดยไม่ต้องคัดลอกรายการไปยังรายการใหม่:
import itertools
for item in itertools.chain(listone, listtwo):
# Do something with each list item
chain
อยู่ทางด้านช้า (แต่ไม่มากนัก) สำหรับสองรายการ แต่เป็นวิธีที่เร็วที่สุดในการโยงหลายรายการ (n >> 2)
>= 3.5
ทางเลือกหลาม:[*l1, *l2]
ทางเลือกอื่นได้รับการแนะนำผ่านการยอมรับPEP 448
ซึ่งสมควรกล่าวถึง
PEP มีชื่อว่าGeneral Unpacking Generalisationโดยทั่วไปจะลดข้อ จำกัด ทางไวยากรณ์เมื่อใช้*
นิพจน์ที่ติดดาวใน Python ด้วยการเข้าร่วมสองรายการ (ใช้ได้กับการทำซ้ำใด ๆ ) สามารถทำได้ด้วย:
>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]
>>> joined_list = [*l1, *l2] # unpack both iterables in a list literal
>>> print(joined_list)
[1, 2, 3, 4, 5, 6]
ฟังก์ชั่นนี้ถูกกำหนดไว้สำหรับ Python3.5
มันไม่ได้รับการย้อนกลับไปยังรุ่นก่อนหน้าใน3.x
ตระกูล ในรุ่นที่ไม่รองรับSyntaxError
จะมีการยกระดับ
เช่นเดียวกับวิธีอื่น ๆ สิ่งนี้ก็สร้างเหมือนสำเนาตื้นขององค์ประกอบในรายการที่สอดคล้องกัน
คว่ำแนวทางนี้คือการที่คุณจริงๆทำรายการไม่ต้องเพื่อที่จะดำเนินการอะไรที่เป็น iterable จะทำ ตามที่ระบุไว้ใน PEP:
นี้ยังเป็นประโยชน์เป็นวิธีที่สามารถอ่านได้มากขึ้นจากข้อสรุป iterables ลงในรายการเช่นซึ่งขณะนี้เทียบเท่ากับเพียง
my_list + list(my_tuple) + list(my_range)
[*my_list, *my_tuple, *my_range]
ดังนั้นในขณะที่การเพิ่ม+
จะเพิ่มTypeError
เนื่องจากชนิดไม่ตรงกัน:
l = [1, 2, 3]
r = range(4, 7)
res = l + r
สิ่งต่อไปนี้จะไม่:
res = [*l, *r]
เพราะมันจะแกะเนื้อหาของ iterables ออกก่อนจากนั้นก็สร้างlist
จากเนื้อหา
res = [*l1, *reversed(l2)]
ตัวอย่างเช่นคุณสามารถกลับหนึ่งของรายการที่คุณกำลังเชื่อมโยง: เนื่องจากreversed
ส่งคืนตัววนซ้ำres = l1 + reversed(l2)
จะทำให้เกิดข้อผิดพลาด
คุณสามารถใช้ชุดเพื่อรับรายการรวมค่าที่ไม่ซ้ำกัน
mergedlist = list(set(listone + listtwo))
listone + [x for x in listtwo if x not in listone]
import collections; mergedlist = list(collections.OrderedDict.fromkeys(listone + listtwo))
จะทำการหลอกลวง
คุณสามารถใช้list.extend()
วิธีนี้เพื่อเพิ่ม a list
ไปยังจุดสิ้นสุดของอีกอันหนึ่ง:
listone = [1,2,3]
listtwo = [4,5,6]
listone.extend(listtwo)
หากคุณต้องการให้รายการดั้งเดิมไม่เปลี่ยนแปลงคุณสามารถสร้างlist
วัตถุใหม่และextend
รายการทั้งสอง:
mergedlist = []
mergedlist.extend(listone)
mergedlist.extend(listtwo)
ฉันจะต่อสองรายการใน Python ได้อย่างไร
จาก 3.7 นี่เป็นวิธีการ stdlib ที่ได้รับความนิยมมากที่สุดสำหรับการต่อสองรายการ (หรือมากกว่า) ในไพ ธ อน
เชิงอรรถ
นี่เป็นวิธีการแก้ปัญหาที่ลื่นเพราะความกระชับ แต่
sum
ดำเนินการเรียงต่อกันแบบคู่ตามลำดับซึ่งหมายความว่านี่เป็นการดำเนินการกำลังสองเนื่องจากต้องจัดสรรหน่วยความจำสำหรับแต่ละขั้นตอน อย่าใช้ถ้ารายการของคุณมีขนาดใหญ่ดู
chain
และchain.from_iterable
จากเอกสาร คุณจะต้องimport itertools
ก่อน การต่อข้อมูลเป็นเชิงเส้นในหน่วยความจำดังนั้นนี่จึงเป็นสิ่งที่ดีที่สุดในแง่ของประสิทธิภาพและความเข้ากันได้ของรุ่นchain.from_iterable
ได้รับการแนะนำใน 2.6วิธีนี้ใช้การแยกบรรจุทั่วไปเพิ่มเติม (PEP 448)แต่ไม่สามารถพูดคุยกับรายการ N ได้เว้นแต่คุณจะแกะกล่องด้วยตนเองด้วยตนเอง
a += b
และa.extend(b)
มีความเท่าเทียมกันมากหรือน้อยสำหรับวัตถุประสงค์ในทางปฏิบัติทั้งหมด+=
เมื่อเรียกในรายการจะโทรภายในlist.__iadd__
ซึ่งขยายรายการแรกโดยที่สอง
การต่อข้อมูล 2 รายการ1
ไม่มีความแตกต่างกันมากระหว่างวิธีการเหล่านี้ แต่นั่นก็สมเหตุสมผลเนื่องจากทุกคนมีลำดับความซับซ้อนเท่ากัน (เป็นเส้นตรง) ไม่มีเหตุผลใดที่จะชอบอันใดอันหนึ่งยกเว้นเป็นเรื่องของสไตล์
การต่อข้อมูล N-List
แปลงได้ถูกสร้างขึ้นโดยใช้โมดูลperfplot รหัสสำหรับการอ้างอิงของคุณ
1. The iadd
( +=
) และextend
วิธีการทำงานในสถานที่ดังนั้นจึงต้องสร้างสำเนาทุกครั้งก่อนการทดสอบ เพื่อให้ทุกสิ่งเป็นไปอย่างยุติธรรมวิธีการทั้งหมดมีขั้นตอนการคัดลอกล่วงหน้าสำหรับรายการทางด้านซ้ายซึ่งสามารถละเว้นได้
ห้ามใช้วิธี DUNDER list.__add__
โดยตรงไม่ว่าในรูปแบบหรือรูปแบบใด ๆ ในความเป็นจริงหลีกเลี่ยงวิธีการ dunder และใช้ผู้ประกอบการและoperator
ฟังก์ชั่นเช่นที่พวกเขาถูกออกแบบมาสำหรับ งูหลามมีความหมายอย่างระมัดระวังอบเข้ามาซึ่งมีความซับซ้อนมากกว่าแค่เรียกเสียงฟ้าร้องโดยตรง นี่คือตัวอย่าง ดังนั้นเพื่อสรุปa.__add__(b)
=> BAD; a + b
=> ดี
คำตอบบางข้อเสนอที่นี่reduce(operator.add, [a, b])
สำหรับการต่อข้อมูลแบบคู่ - นี่เป็นคำเดียวที่sum([a, b], [])
มากกว่า
วิธีใดก็ตามที่ใช้set
จะทำให้รายการซ้ำซ้อนและสูญเสียการสั่งซื้อ ใช้ด้วยความระมัดระวัง
for i in b: a.append(i)
เป็นคำที่มากขึ้นและช้ากว่าa.extend(b)
ซึ่งเป็นฟังก์ชั่นการโทรเดียวและสำนวนมากขึ้น append
ช้าลงเนื่องจากความหมายที่มีการจัดสรรและพัฒนาหน่วยความจำสำหรับรายการ ดูที่นี่สำหรับการสนทนาที่คล้ายกัน
heapq.merge
จะใช้งานได้ แต่กรณีการใช้งานนั้นใช้สำหรับการรวมรายการที่เรียงลำดับในเวลาเชิงเส้น การใช้มันในสถานการณ์อื่น ๆ เป็นการป้องกันรูปแบบ
yield
องค์ประกอบรายการจากฟังก์ชั่นเป็นวิธีที่ยอมรับได้ แต่chain
ทำสิ่งนี้ได้เร็วขึ้นและดีขึ้น (มันมีโค้ดพา ธ ใน C ดังนั้นมันจึงเร็ว)
operator.add(a, b)
a + b
เป็นที่ยอมรับการทำงานเทียบเท่า มันเป็นกรณีการใช้งานส่วนใหญ่สำหรับวิธีการจัดส่งแบบไดนามิก มิฉะนั้นต้องการa + b
ซึ่งเป็นสั้นและอ่านได้มากขึ้นในความคิดของฉัน YMMV
"There's not much difference between these methods but that makes sense given they all have the same order of complexity (linear). There's no particular reason to prefer one over the other except as a matter of style.
"วิธีแก้ไขปัญหาไม่ได้อยู่ในคำตอบของฉันหรือวิจารณ์ใน" ความคิดเห็น "ฉันแนะนำให้ไม่ใช้
มันค่อนข้างง่ายและฉันคิดว่ามันแสดงให้เห็นในบทช่วยสอน :
>>> listone = [1,2,3]
>>> listtwo = [4,5,6]
>>>
>>> listone + listtwo
[1, 2, 3, 4, 5, 6]
คำถามนี้ถามโดยตรงเกี่ยวกับการเข้าร่วมสองรายการ อย่างไรก็ตามมันค่อนข้างสูงในการค้นหาแม้ว่าคุณกำลังมองหาวิธีการเข้าร่วมหลายรายการ (รวมถึงกรณีเมื่อคุณเข้าร่วมรายการศูนย์)
ฉันคิดว่าตัวเลือกที่ดีที่สุดคือการใช้ list comprehensions:
>>> a = [[1,2,3], [4,5,6], [7,8,9]]
>>> [x for xs in a for x in xs]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
คุณสามารถสร้างเครื่องกำเนิดไฟฟ้าได้เช่นกัน:
>>> map(str, (x for xs in a for x in xs))
['1', '2', '3', '4', '5', '6', '7', '8', '9']
คำตอบเก่า
พิจารณาวิธีการทั่วไปที่มากกว่านี้:
a = [[1,2,3], [4,5,6], [7,8,9]]
reduce(lambda c, x: c + x, a, [])
จะส่งออก:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
หมายเหตุนี้ยังใช้งานได้อย่างถูกต้องเมื่อa
เป็นหรือ[]
[[1,2,3]]
อย่างไรก็ตามสามารถทำได้อย่างมีประสิทธิภาพด้วยitertools
:
a = [[1,2,3], [4,5,6], [7,8,9]]
list(itertools.chain(*a))
หากคุณไม่จำเป็นต้องมีlist
แต่เพียง iterable list()
ละเว้น
ปรับปรุง
ทางเลือกที่แพทริคคอลลินส์แนะนำในการแสดงความคิดเห็นอาจช่วยคุณได้เช่นกัน:
sum(a, [])
reduce
ตอนนี้อยู่ในfunctools
ดังนั้นคุณจะต้องนำเข้าก่อน
คุณสามารถใช้+
หรือ+=
ตัวดำเนินการดังต่อไปนี้:
a = [1, 2, 3]
b = [4, 5, 6]
c = a + b
หรือ:
c = []
a = [1, 2, 3]
b = [4, 5, 6]
c += (a + b)
นอกจากนี้หากคุณต้องการให้ค่าในรายการที่ผสานเป็นค่าเฉพาะคุณสามารถทำได้:
c = list(set(a + b))
list(dict.fromkeys(a + b))
มันเป็นที่น่าสังเกตว่าitertools.chain
ฟังก์ชั่นยอมรับจำนวนตัวแปรของการขัดแย้ง:
>>> l1 = ['a']; l2 = ['b', 'c']; l3 = ['d', 'e', 'f']
>>> [i for i in itertools.chain(l1, l2)]
['a', 'b', 'c']
>>> [i for i in itertools.chain(l1, l2, l3)]
['a', 'b', 'c', 'd', 'e', 'f']
หาก iterable (tuple, list, generator, ฯลฯ ) เป็นอินพุตfrom_iterable
วิธีการเรียนอาจจะใช้:
>>> il = [['a'], ['b', 'c'], ['d', 'e', 'f']]
>>> [i for i in itertools.chain.from_iterable(il)]
['a', 'b', 'c', 'd', 'e', 'f']
ด้วย Python 3.3+ คุณสามารถใช้ผลตอบแทนจาก :
listone = [1,2,3]
listtwo = [4,5,6]
def merge(l1, l2):
yield from l1
yield from l2
>>> list(merge(listone, listtwo))
[1, 2, 3, 4, 5, 6]
หรือถ้าคุณต้องการสนับสนุนจำนวนตัววนซ้ำโดยพลการ:
def merge(*iters):
for it in iters:
yield from it
>>> list(merge(listone, listtwo, 'abcd', [20, 21, 22]))
[1, 2, 3, 4, 5, 6, 'a', 'b', 'c', 'd', 20, 21, 22]
itertools.chain
(ซึ่งเทียบเท่า) แทนการกำหนดฟังก์ชั่นของคุณเอง
หากคุณต้องการรวมสองรายการในรูปแบบที่เรียงลำดับคุณสามารถใช้merge
ฟังก์ชันจากheapq
ไลบรารี
from heapq import merge
a = [1, 2, 4]
b = [2, 4, 6, 7]
print list(merge(a, b))
หากคุณไม่สามารถใช้ตัวดำเนินการบวก ( +
) คุณสามารถใช้operator
การนำเข้า:
import operator
listone = [1,2,3]
listtwo = [4,5,6]
result = operator.add(listone, listtwo)
print(result)
>>> [1, 2, 3, 4, 5, 6]
หรือคุณสามารถใช้ฟังก์ชัน__add__
dunder :
listone = [1,2,3]
listtwo = [4,5,6]
result = list.__add__(listone, listtwo)
print(result)
>>> [1, 2, 3, 4, 5, 6]
+
operator.add
วิธีทั่วไปสำหรับรายการเพิ่มเติมคุณสามารถใส่ไว้ในรายการและใช้ฟังก์ชันitertools.chain.from_iterable()
1ซึ่งยึดตามคำตอบนี้เป็นวิธีที่ดีที่สุดสำหรับการเรียงรายการที่ซ้อนกัน:
>>> l=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> import itertools
>>> list(itertools.chain.from_iterable(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
1. โปรดทราบว่าchain.from_iterable()
มีให้ใน Python 2.6 และใหม่กว่า ในรุ่นอื่น ๆ chain(*l)
ใช้
หากคุณต้องการรวมรายการที่เรียงลำดับสองรายการด้วยกฎการเรียงลำดับที่ซับซ้อนคุณอาจต้องหมุนรายการด้วยตนเองในรหัสต่อไปนี้ (โดยใช้กฎการเรียงลำดับแบบง่าย ๆ เพื่อให้อ่านง่าย :-))
list1 = [1,2,5]
list2 = [2,3,4]
newlist = []
while list1 and list2:
if list1[0] == list2[0]:
newlist.append(list1.pop(0))
list2.pop(0)
elif list1[0] < list2[0]:
newlist.append(list1.pop(0))
else:
newlist.append(list2.pop(0))
if list1:
newlist.extend(list1)
if list2:
newlist.extend(list2)
assert(newlist == [1, 2, 3, 4, 5])
heapq.merge
หรือการใช้งานเพียงแค่
คุณสามารถใช้append()
วิธีการที่กำหนดไว้ในlist
วัตถุ:
mergedlist =[]
for elem in listone:
mergedlist.append(elem)
for elem in listtwo:
mergedlist.append(elem)
list(set(listone) | set(listtwo))
รหัสข้างต้นไม่รักษาคำสั่งลบซ้ำจากแต่ละรายการ (แต่ไม่ได้มาจากรายการตัดแบ่ง)
ตามที่หลายคนชี้ไปแล้วitertools.chain()
เป็นวิธีที่จะไปหากจำเป็นต้องใช้การรักษาแบบเดียวกันกับทั้งสองรายการ ในกรณีของฉันฉันมีป้ายกำกับและธงซึ่งแตกต่างจากรายการหนึ่งไปอีกรายการหนึ่งดังนั้นฉันต้องการบางสิ่งที่ซับซ้อนกว่าเล็กน้อย เมื่อมันปรากฏออกมาเบื้องหลังitertools.chain()
จะทำสิ่งต่อไปนี้:
for it in iterables:
for element in it:
yield element
(ดูhttps://docs.python.org/2/library/itertools.html ) ดังนั้นฉันจึงได้แรงบันดาลใจจากที่นี่และเขียนบางสิ่งตามบรรทัดเหล่านี้:
for iterable, header, flag in ( (newList, 'New', ''), (modList, 'Modified', '-f')):
print header + ':'
for path in iterable:
[...]
command = 'cp -r' if os.path.isdir(srcPath) else 'cp'
print >> SCRIPT , command, flag, srcPath, mergedDirPath
[...]
ประเด็นหลักที่ต้องทำความเข้าใจที่นี่คือรายการเป็นเพียงกรณีพิเศษของ iterable ซึ่งเป็นวัตถุที่เหมือนกัน และfor ... in
ลูปในไพ ธ อนสามารถทำงานกับตัวแปรทูเพิลได้ดังนั้นจึงง่ายต่อการวนซ้ำกับตัวแปรหลายตัวในเวลาเดียวกัน
ใช้รายการเข้าใจง่าย:
joined_list = [item for list_ in [list_one, list_two] for item in list_]
มันมีข้อดีทั้งหมดของวิธีการใหม่ล่าสุดในการใช้General Unpacking Generalizationsเช่นคุณสามารถเชื่อมต่อจำนวน iterables ที่แตกต่างกันตามอำเภอใจ (ตัวอย่างเช่น list, tuples, range, และ generators) แบบนั้น - และไม่ จำกัด Python 3.5 หรือใหม่กว่า .
วิธีกระชับรายการรวมของรายการคือ
list_of_lists = [[1,2,3], [4,5,6], [7,8,9]]
reduce(list.__add__, list_of_lists)
ซึ่งทำให้เรา
[1, 2, 3, 4, 5, 6, 7, 8, 9]
list.__add__
ใช้operator.add
แทน นี่เป็นสิ่งที่เทียบเท่ากับคำพูดsum(list_of_lists, [])
ที่เลวร้าย ไม่ได้ใช้!
obj.__class__
และobj.__dict__
.
ใน Python คุณสามารถเชื่อมมิติที่เข้ากันได้สองอาร์เรย์เข้าด้วยกันด้วยคำสั่งนี้
numpy.concatenate([a,b])
ดังนั้นมีสองวิธีง่าย ๆ
+
: มันสร้างรายการใหม่จากรายการที่ให้ไว้ตัวอย่าง:
In [1]: a = [1, 2, 3]
In [2]: b = [4, 5, 6]
In [3]: a + b
Out[3]: [1, 2, 3, 4, 5, 6]
In [4]: %timeit a + b
10000000 loops, best of 3: 126 ns per loop
ตัวอย่าง:
In [1]: a = [1, 2, 3]
In [2]: b = [4, 5, 6]
In [3]: %timeit a.extend(b)
10000000 loops, best of 3: 91.1 ns per loop
ดังนั้นเราเห็นว่าวิธีการยอดนิยมสองวิธีextend
นั้นมีประสิทธิภาพ
มีหลายวิธีในการเชื่อมต่อรายการในงูหลาม
l1 = [1,2,3,4]
l2 = [3,4,5,6]
1. new_list = l1.extend(l2)
2. new_list = l1 + l2
3. new_list = [*l1, *l2]
import itertools
A = list(zip([1,3,5,7,9],[2,4,6,8,10]))
B = [1,3,5,7,9]+[2,4,6,8,10]
C = list(set([1,3,5,7,9] + [2,4,6,8,10]))
D = [1,3,5,7,9]
D.append([2,4,6,8,10])
E = [1,3,5,7,9]
E.extend([2,4,6,8,10])
F = []
for a in itertools.chain([1,3,5,7,9], [2,4,6,8,10]):
F.append(a)
print ("A: " + str(A))
print ("B: " + str(B))
print ("C: " + str(C))
print ("D: " + str(D))
print ("E: " + str(E))
print ("F: " + str(F))
เอาท์พุท:
A: [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
B: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
C: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
D: [1, 3, 5, 7, 9, [2, 4, 6, 8, 10]]
E: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
F: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
หากคุณต้องการรายการใหม่ในขณะที่รักษารายการเก่าสองรายการ:
def concatenate_list(listOne, listTwo):
joinedList = []
for i in listOne:
joinedList.append(i)
for j in listTwo:
joinedList.append(j)
sorted(joinedList)
return joinedList
คุณอาจปฏิบัติตามรหัส
listone = [1, 2, 3]
listtwo = [4, 5, 6]
for i in listone:
listtwo.append(i)
print(listtwo)
[1,2,3,4,5,6]