لا يمكن فرز الجدول مع الفهارس الترابطية
-
21-09-2019 - |
سؤال
لماذا لا يمكنني استخدام table.sort لفرز الجداول مع الفهارس الترابطية؟
المحلول
يمكنك فقط فرز الجداول باستخدام مفاتيح عدد صحيح متتالية تبدأ من 1 ، أي قوائم. إذا كان لديك جدول آخر من أزواج القيمة الرئيسية ، فيمكنك عمل قائمة من الأزواج وفرز ما:
function sortpairs(t, lt)
local u = { }
for k, v in pairs(t) do table.insert(u, { key = k, value = v }) end
table.sort(u, lt)
return u
end
بالطبع هذا مفيد فقط إذا قدمت طلبًا مخصصًا (lt
) الذي يتوقع كأزواج مفتاح/القيمة.
تمت مناقشة هذه القضية بإسهاب في أ سؤال ذي صلة حول فرز جداول لوا.
نصائح أخرى
بشكل عام ، طاولات لوا هي صفائف ترابطية خالصة. لا يوجد ترتيب "طبيعي" بخلاف الآثار الجانبية لتنفيذ جدول التجزئة المعين المستخدم في قلب LUA. هذا أمر منطقي لأن قيم أي نوع من بيانات LUA (بخلاف غير ذلك nil
) يمكن استخدامها كمفتاح وقيم ؛ ولكن فقط الأوتار والأرقام لديها أي نوع من الطلبات المعقولة ، ثم فقط بين قيم نوع مماثلة.
على سبيل المثال ، ما يجب أن يكون ترتيب هذا الجدول المفرز:
unsortable = {
answer=42,
true="Beauty",
[function() return 17 end] = function() return 42 end,
[math.pi] = "pi",
[ {} ] = {},
12, 11, 10, 9, 8
}
يحتوي على مفتاح سلسلة واحد ، مفتاح واحد منطقي ، مفتاح وظيفة واحد ، مفتاح واحد غير انهياري ، مفتاح جدول واحد ، وخمس مفاتيح عدد صحيح. هل يجب أن تكون الوظيفة قبل السلسلة؟ كيف تقارن السلسلة برقم؟ أين يجب أن يكون الجدول فرز؟ وماذا عن userdata
و thread
القيم التي لا تظهر في هذا الجدول؟
من خلال الاتفاقية ، يتم استخدام القيم المفهرسة بواسطة أعداد صحيحة متتابعة بدءًا من 1 كقوائم. العديد من الوظائف والتعابير الشائعة تتبع هذه الاتفاقية ، و table.sort
مثال واحد. عادة ما تتجاهل الوظائف التي تعمل على القوائم أي قيم مخزنة في مفاتيح ليست جزءًا من القائمة. تكرارا، table.sort
مثال: إنه لا يفرز سوى العناصر التي يتم تخزينها في المفاتيح التي تشكل جزءًا من القائمة.
مثال آخر هو #
المشغل أو العامل. للجدول أعلاه ، #unsortable
هو 5 لأن unsortable[5] ~= nil
و unsortable[6] == nil
. لاحظ أن القيمة المخزنة في الفهرس الرقمي math.pi
لا يتم حسابه على الرغم من أن PI يتراوح بين 3 و 4 لأنه ليس عددًا صحيحًا. علاوة على ذلك ، لا يتم حساب أي من المفاتيح الأخرى غير الأخرى. هذا يعني أن البسيط للحلقة يمكن أن يتكرر على القائمة بأكملها:
for i in 1,#unsortable do
print(i,unsortable[i])
end
على الرغم من أن هذا غالب
for i,v in ipairs(unsortable) do
print(i,v)
end
باختصار ، جداول LUA هي مجموعات غير مرتبة من القيم ، كل فهرسة بواسطة مفتاح ؛ ولكن هناك اتفاقية خاصة لمفاتيح عدد صحيح متتابع تبدأ في 1.
تعديل: بالنسبة للحالة الخاصة للمفاتيح غير المتكاملة مع ترتيب جزئي مناسب ، يوجد عمل يتضمن جدول فهرس منفصل. يعد المحتوى الموصوف للجداول المسمى بواسطة قيم السلسلة مثالًا مناسبًا لهذه الخدعة.
أولاً ، جمع المفاتيح في جدول جديد ، في شكل قائمة. وهذا يعني ، اجعل جدولًا مفهرسة بواسطة أعداد صحيحة متتالية تبدأ من 1 مع مفاتيح كقيم وفرز ذلك. ثم ، استخدم هذا الفهرس للتكرار عبر الجدول الأصلي بالترتيب المطلوب.
على سبيل المثال ، هنا هو foreachinorder()
, ، والتي تستخدم هذه التقنية للتكرار على جميع قيم الجدول ، واتصال دالة لكل زوج مفتاح/قيمة ، بترتيب يحدده وظيفة المقارنة.
function foreachinorder(t, f, cmp)
-- first extract a list of the keys from t
local keys = {}
for k,_ in pairs(t) do
keys[#keys+1] = k
end
-- sort the keys according to the function cmp. If cmp
-- is omitted, table.sort() defaults to the < operator
table.sort(keys,cmp)
-- finally, loop over the keys in sorted order, and operate
-- on elements of t
for _,k in ipairs(keys) do
f(k,t[k])
end
end
يقوم ببناء فهرس ، وفرزه table.sort()
, ، ثم الحلقات فوق كل عنصر في الفهرس المصنف ويدعو الوظيفة f
لكل واحد. الوظيفة f
يتم تمرير المفتاح والقيمة. يتم تحديد ترتيب الفرز بواسطة وظيفة مقارنة اختيارية يتم تمريرها إلى table.sort
. يطلق عليه مع عنصرين للمقارنة (المفاتيح إلى الجدول t
في هذه الحالة) ويجب أن تعود true
إذا كان الأول أقل من الثانية. إذا تم حذفه ، table.sort
يستخدم المدمج <
المشغل أو العامل.
على سبيل المثال ، بالنظر إلى الجدول التالي:
t1 = {
a = 1,
b = 2,
c = 3,
}
من ثم foreachinorder(t1,print)
مطبوعات:
a 1 b 2 c 3
و foreachinorder(t1,print,function(a,b) return a>b end)
مطبوعات:
c 3 b 2 a 1
لأنهم ليس لديهم أي أمر في المقام الأول. إنه مثل محاولة فرز حقيبة قمامة مليئة بالموز.