تفتقر شرائح Go، وهي مصفوفات ديناميكية توفر معالجة مرنة للبيانات، إلى دالة “حذف” مباشرة. يقتضي إزالة العناصر اتباع نهج مختلف. تُفصّل هذه المقالة تقنيات فعّالة، مع التركيز على تقسيم الشرائح لتحقيق الأداء الأمثل.
محتويات الجدول
حذف عنصر واحد
الطريقة الأكثر كفاءة لإزالة عنصر واحد هي إنشاء شريحة جديدة تستبعد العنصر المستهدف. يستفيد هذا من قدرات تقسيم الشرائح في Go، مما يخلق عرضًا في المصفوفة الأساسية دون نسخ المصفوفة بالكامل. هذا أسرع بكثير من الطرق التي تتضمن الإضافة أو نسخ العنصر الفردي، خاصةً بالنسبة للشرائح الكبيرة.
package main
import "fmt"
func main() {
mySlice := []int{10, 20, 30, 40, 50}
indexToDelete := 2 // حذف العنصر في الفهرس 2 (القيمة 30)
newSlice := append(mySlice[:indexToDelete], mySlice[indexToDelete+1:]...)
fmt.Println("الشريحة الأصلية:", mySlice)
fmt.Println("الشريحة بعد الحذف:", newSlice)
}
يقوم هذا الكود بإنشاء newSlice
عن طريق إضافة شريحتين فرعيتين: mySlice[:indexToDelete]
(العناصر قبل الهدف) و mySlice[indexToDelete+1:]
(العناصر بعد الهدف). يعمل عامل الحذف (…) على تفريغ الشريحة الثانية للإضافة. تظل mySlice
الأصلية دون تغيير.
حذف عناصر متعددة
إن توسيع نهج تقسيم الشرائح لإزالة عناصر متعددة ليس مباشرًا، ولكنه لا يزال أكثر كفاءة من الإضافة التكرارية للشرائح الأكبر. في حين أن عملية شريحة فرعية موجزة واحدة غير ممكنة، يمكننا تحسين العملية لتقليل التخصيصات.
package main
import "fmt"
func main() {
mySlice := []int{10, 20, 30, 40, 50}
indicesToDelete := []int{1, 3} // فهرس الحذف
newSlice := make([]int, 0, len(mySlice)-len(indicesToDelete)) // تخصيص مسبق للكفاءة
for i, val := range mySlice {
shouldDelete := false
for _, index := range indicesToDelete {
if i == index {
shouldDelete = true
break
}
}
if !shouldDelete {
newSlice = append(newSlice, val)
}
}
fmt.Println("الشريحة الأصلية:", mySlice)
fmt.Println("الشريحة بعد الحذف:", newSlice)
}
يخصص هذا المثال المحسّن newSlice
مسبقًا لتقليل التخصيصات أثناء الإضافة، مما يعزز الكفاءة. يقوم بالتكرار، والتحقق من indicesToDelete
، وإضافة العناصر التي يجب الاحتفاظ بها فقط.
حذف عناصر بناءً على شرط
غالبًا ما يتطلب إزالة العناصر بناءً على شرط التكرار. على الرغم من أنه أقل كفاءة من تقسيم الشرائح لحذف العناصر المفردة، إلا أنه ضروري للإزالة الشرطية.
package main
import "fmt"
func main() {
mySlice := []int{10, 20, 30, 40, 50}
newSlice := make([]int, 0, len(mySlice)) // تخصيص مسبق للكفاءة
for _, val := range mySlice {
if val != 30 { // حذف العناصر التي تساوي 30
newSlice = append(newSlice, val)
}
}
fmt.Println("الشريحة الأصلية:", mySlice)
fmt.Println("الشريحة بعد الحذف:", newSlice)
}
يُصفّي هذا المثال العناصر بناءً على الشرط val != 30
. يُحسّن التخصيص المسبق لـ newSlice
الأداء. بالنسبة للشرائح الكبيرة وحذف الشرط المتكرر، ضع في اعتبارك تقنيات أكثر تقدمًا مثل الترشيح باستخدام دالة منفصلة أو استخدام بنية بيانات مختلفة.
اعتبارات الأداء
بالنسبة لإزالة عنصر واحد، يظل تقسيم الشرائح النهج الأكثر كفاءة. غالبًا ما تتطلب عمليات الحذف المتعددة أو الشرطية التكرار، ولكن التخصيص المسبق للشريحة الناتجة يخفف بشكل كبير من تدهور الأداء. أعطِ الأولوية دائمًا لتقسيم الشرائح عند الاقتضاء لتحقيق الأداء الأمثل، خاصةً مع مجموعات البيانات الكبيرة.