سؤال

لماذا لا يمكنني استخدام 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

لأنهم ليس لديهم أي أمر في المقام الأول. إنه مثل محاولة فرز حقيبة قمامة مليئة بالموز.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top