سؤال

sorted([2, float('nan'), 1]) عائدات [2, nan, 1]

(على الأقل على تنفيذ Python 3.1.)

أفهم nan هو كائن غريب ، لذلك لن أفاجأ إذا ظهر في أماكن عشوائية في نتيجة الفرز. لكنه يفسد أيضًا هذا النوع من الأرقام غير النانوية في الحاوية ، وهو أمر غير متوقع حقًا.

سألت أ السؤال ذي الصلة حول max, ، وبناءً على ذلك ، أفهم لماذا sort يعمل مثل هذا. ولكن هل يجب أن يعتبر هذا خطأ؟

الوثائق تقول فقط "إرجاع قائمة مصنفة جديدة [...] دون تحديد أي تفاصيل.

تحرير: أوافق الآن على أن هذا لا ينتهك معيار IEEE. ومع ذلك ، فهو خطأ من أي وجهة نظر الحس السليم ، على ما أعتقد. حتى Microsoft ، التي لم تكن معروفة بأنها تعترف بأخطائها في كثير من الأحيان ، قد أدركت هذا الشخص على أنه خطأ ، وقام بإصلاحه في أحدث إصدار: http://connect.microsoft.com/visualstudio/feedback/details/363379/bug-in-list-double-sort-.

على أي حال ، انتهى بي الأمر بعد إجابة @خاتشيك:

sorted(list_, key = lambda x : float('-inf') if math.isnan(x) else x)

أظن أنه ينتج عنه نجاح أداء مقارنة باللغة التي تقوم بها بشكل افتراضي ، ولكنها على الأقل تعمل (باستثناء أي أخطاء قدمتها).

هل كانت مفيدة؟

المحلول

الإجابات السابقة مفيدة ، ولكن ربما لم تكن واضحة فيما يتعلق بجذر المشكلة.

في أي لغة ، تنطبق الفرز طلبًا معينًا ، يتم تعريفه بواسطة وظيفة المقارنة أو بطريقة أخرى ، على مجال قيم الإدخال. على سبيل المثال ، أقل من ذلك ، ويعرف أيضًا باسم operator <, يمكن استخدامها في جميع أنحاء إذا وفقط إذا كان أقل من تحديد الطلب المناسب على قيم الإدخال.

ولكن هذا ليس صحيحًا على وجه التحديد بالنسبة لقيم النقاط العائمة وأقل من ذلك: "NAN غير مرتبة: لا يساوي ، أو أقل من أي شيء ، بما في ذلك نفسه". ((نثر واضح من دليل GNU C ، ولكن ينطبق على كل الحديث IEEE754 على أساس النقطة العائمة)

لذا فإن الحلول الممكنة هي:

  1. قم بإزالة NANS أولاً ، مما يجعل مجال الإدخال محدد جيدًا عبر <(أو وظيفة الفرز الأخرى المستخدمة)
  2. حدد وظيفة المقارنة المخصصة (المعروفة أيضًا باسم المسند) التي تحدد طلبًا لل NAN ، مثل أقل من أي رقم ، أو أكبر من أي رقم.

يمكن استخدام أي من النهج ، بأي لغة.

من الناحية العملية ، بالنظر إلى Python ، أفضل إزالة NANS إذا كنت إما لا تهتم كثيرًا بالأداء الأسرع أو إذا كان إزالة NANS هو السلوك المطلوب في السياق.

وإلا يمكنك استخدام وظيفة مسند مناسبة عبر "CMP" في إصدارات Python الأقدم ، أو عبر هذا و functools.cmp_to_key(). هذا الأخير أكثر حرجًا ، بشكل طبيعي ، من إزالة NANS أولاً. وستكون هناك حاجة إلى رعاية لتجنب أسوأ الأداء ، عند تحديد هذه الوظيفة المسند.

نصائح أخرى

المشكلة هي أنه لا يوجد ترتيب صحيح إذا كانت القائمة تحتوي على NAN ، نظرًا لأن تسلسل A1 ، A2 ، A3 ، ... ، يتم فرز A إذا A1 <= A2 <= A3 <= ... <= an. إذا كان أي من هذه القيم A عبارة عن نان ، فإن الخاصية المرتبة تنفصل ، لأنه على الرغم من كل A ، A <= nan و nan <= a كلاهما خطأ.

لست متأكدًا من الخلل ، لكن الحل الحل هو ما يلي:

sorted(
    (2, 1, float('nan')),
    lambda x,y: x is float('nan') and -1 
                or (y is float('nan') and 1
                or cmp(x,y)))

مما يؤدي إلى:

('nan', 1, 2)

أو إزالة nanق قبل الفرز أو أي شيء آخر.

IEEE754 هو المعيار الذي يحدد عمليات النقطة العائمة في هذه الحالة. يحدد هذا المعيار عملية المقارنة بين المعاملات ، على الأقل واحد منها هو نان ، ليكون خطأ. وبالتالي ، هذا ليس خطأ. تحتاج إلى التعامل مع NANS قبل العمل على صفيفك.

على افتراض أنك ترغب في الاحتفاظ بـ NANS وطلبها كأدنى "القيم" نان غير الهاوية, نان نابري فريدة من نوعها, عددي و غير عددي أشياء:

def is_nan(x):
    return (x is np.nan or x != x)

list_ = [2, float('nan'), 'z', 1, 'a', np.nan, 4, float('nan')]
sorted(list_, key = lambda x : float('-inf') if is_nan(x) else x)
# [nan, nan, nan, 1, 2, 4, 'a', 'z']
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top