ในคำตอบนี้จะเป็นสองส่วน: สองโซลูชันที่ไม่ซ้ำกันและกราฟความเร็วสำหรับโซลูชันเฉพาะ
การลบรายการซ้ำ
คำตอบส่วนใหญ่เหล่านี้เพียงลบรายการที่ซ้ำกันซึ่งแฮชได้ แต่คำถามนี้ไม่ได้หมายความว่ามันไม่เพียงต้องการไอเท็มที่สับได้ซึ่งหมายความว่าฉันจะเสนอโซลูชั่นที่ไม่ต้องใช้รายการที่แฮช
collection.Counterเป็นเครื่องมือที่มีประสิทธิภาพในไลบรารีมาตรฐานซึ่งอาจเหมาะสำหรับสิ่งนี้ มีอีกวิธีแก้ปัญหาเดียวที่มี Counter อยู่ด้วย อย่างไรก็ตามวิธีการแก้ปัญหานั้นยัง จำกัด อยู่ที่ปุ่มhashable
ในการอนุญาตให้ใช้คีย์ที่ไม่สามารถล้างได้ในตัวนับฉันได้สร้างคลาสคอนเทนเนอร์ซึ่งจะพยายามรับฟังก์ชั่นแฮชเริ่มต้นของวัตถุ แต่ถ้ามันล้มเหลวมันจะลองใช้ฟังก์ชันตัวตน นอกจากนี้ยังกำหนดEQและกัญชาวิธี นี่ควรจะเพียงพอที่จะอนุญาตรายการที่ล้างไม่ได้ในโซลูชันของเรา วัตถุที่ไม่สามารถล้างได้จะได้รับการปฏิบัติเสมือนเป็นวัตถุที่ถูกแฮช อย่างไรก็ตามฟังก์ชันแฮชนี้ใช้รหัสประจำตัวสำหรับวัตถุที่ unhashable ซึ่งหมายความว่าวัตถุสองเท่าที่ทั้งสองไม่สามารถล้างได้จะไม่ทำงาน ฉันขอแนะนำให้คุณเอาชนะสิ่งนี้และเปลี่ยนให้ใช้แฮชของประเภทที่ไม่แน่นอนที่เทียบเท่าได้ (เช่นใช้hash(tuple(my_list))
ถ้าmy_list
เป็นรายการ)
ฉันทำสองวิธีด้วยกัน โซลูชันอื่นที่เก็บลำดับของรายการโดยใช้คลาสย่อยของทั้ง OrderedDict และ Counter ซึ่งมีชื่อว่า 'OrderedCounter' ตอนนี้นี่คือฟังก์ชั่น:
from collections import OrderedDict, Counter
class Container:
def __init__(self, obj):
self.obj = obj
def __eq__(self, obj):
return self.obj == obj
def __hash__(self):
try:
return hash(self.obj)
except:
return id(self.obj)
class OrderedCounter(Counter, OrderedDict):
'Counter that remembers the order elements are first encountered'
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
def remd(sequence):
cnt = Counter()
for x in sequence:
cnt[Container(x)] += 1
return [item.obj for item in cnt]
def oremd(sequence):
cnt = OrderedCounter()
for x in sequence:
cnt[Container(x)] += 1
return [item.obj for item in cnt]
remd คือการเรียงลำดับที่ไม่ได้รับคำสั่ง oremd ถูกเรียงลำดับแล้วเรียงลำดับ คุณสามารถบอกได้ชัดเจนว่าอันไหนเร็วกว่า แต่ฉันจะอธิบายต่อไป การเรียงลำดับที่ไม่ได้รับคำสั่งนั้นเร็วกว่าเล็กน้อย มันเก็บข้อมูลน้อยลงเนื่องจากไม่ต้องการสั่งซื้อ
ตอนนี้ฉันยังต้องการแสดงการเปรียบเทียบความเร็วของคำตอบแต่ละข้อด้วย ดังนั้นฉันจะทำตอนนี้
ฟังก์ชั่นใดเร็วที่สุด?
สำหรับการลบรายการที่ซ้ำกันฉันรวบรวม 10 ฟังก์ชั่นจากคำตอบเล็กน้อย ฉันคำนวณความเร็วของแต่ละฟังก์ชั่นและใส่ลงในกราฟโดยใช้matplotlib.pyplot matplotlib.pyplot
ฉันแบ่งสิ่งนี้ออกเป็นสามรอบของกราฟ hashable คือวัตถุใด ๆ ที่สามารถแฮชและ unhashable คือวัตถุใด ๆ ที่ไม่สามารถแฮชได้ ลำดับที่ได้รับคำสั่งคือลำดับที่รักษาการเรียงลำดับลำดับที่ไม่เรียงลำดับจะไม่รักษาลำดับไว้ ต่อไปนี้เป็นคำศัพท์เพิ่มเติมอีกสองสามข้อ:
Unordered Hashableสำหรับวิธีการใด ๆ ที่นำรายการที่ซ้ำกันออกซึ่งไม่จำเป็นต้องเก็บคำสั่งซื้อไว้ มันไม่ต้องทำงานเพื่อ unhashables แต่ก็ทำได้
Hashable ที่สั่งไว้มีไว้สำหรับวิธีการใด ๆ ที่รักษาลำดับของรายการไว้ในรายการ แต่ไม่จำเป็นต้องใช้สำหรับ unhashables แต่สามารถทำได้
สั่ง Unhashableเป็นวิธีการใด ๆ ที่เก็บคำสั่งของรายการในรายการและทำงานเพื่อ unhashables
บนแกน y คือจำนวนวินาทีที่ใช้
บนแกน x คือหมายเลขที่ฟังก์ชันใช้งาน
เราสร้างลำดับสำหรับ hashables ที่ไม่ได้เรียงลำดับและสั่ง hashables ด้วยความเข้าใจดังต่อไปนี้: [list(range(x)) + list(range(x)) for x in range(0, 1000, 10)]
สำหรับ unhashables ที่สั่งซื้อ: [[list(range(y)) + list(range(y)) for y in range(x)] for x in range(0, 1000, 10)]
โปรดทราบว่ามี 'ขั้นตอน' อยู่ในช่วงเนื่องจากไม่มีมันจะใช้เวลานานถึง 10 เท่า เพราะในความเห็นส่วนตัวของฉันฉันคิดว่ามันอาจจะดูง่ายกว่าเล็กน้อยในการอ่าน
ยังทราบว่าปุ่มต่างๆในตำนานนั้นเป็นสิ่งที่ฉันพยายามจะเดาว่าเป็นส่วนที่สำคัญที่สุดของฟังก์ชั่น ฟังก์ชั่นใดที่แย่ที่สุดหรือดีที่สุด? กราฟพูดด้วยตนเอง
เมื่อตัดสินแล้วนี่คือกราฟ
Hashables ที่ไม่ได้สั่ง
(ซูมเข้า)
Hashables สั่ง
(ซูมเข้า)
สั่ง Unhashables
(ซูมเข้า)