سؤال

لدي دالة تحصل على x(قيمة) وxs(قائمة) وتزيل كافة القيم الأكبر من x من القائمة.حسنًا، إنه لا يعمل، هل يمكنك أن تخبرني لماذا؟

(defun biggerElems(x xs) 
  (let ((xst))
    (dolist (elem xs)
      (if (> x elem)
          (setf xst (remove elem xs))))
    xst))
هل كانت مفيدة؟

المحلول

أعتقد أن هذا الخط غير صحيح:

(setf xst (remove elem xs))))

الحجة الأولى ل setf هو المكان، تليها القيمة.يبدو أنك حصلت عليه إلى الوراء (و xst اما nil أو غير مهيأ).

قد تجد أنه من الأسهل القيام بذلك:

(defun biggerElems (x xs)
  (remove-if (lambda (item) (> item x)) xs))

نصائح أخرى

الأكثر إيجازًا AFAIK:

(defun bigger-elements (x xs) (remove x xs :test #'<))

بإرجاع قائمة جديدة، فإنه يزيل جميع العناصر y من xs الخاصة بها

(< y x)

أو باستخدام الحلقة الشهيرة:

(defun bigger-elements-2 (x xs) 
  (loop for e in xs
        unless (< e x)
        collect e))

عملت على هذا النحو:

(defun filterBig (x xs)
  (remove-if (lambda (item) (> item x)) xs))

ما هو "#" ل؟ولم يجمع معها.

إذا كنت تريد القيام بذلك بطريقة Lisp، فيمكنك استخدام التكرار لإرجاع القائمة الجديدة:

(defun biggerElems (x xs)
  (cond ((null xs) NIL)
        ((< x (car xs))
         (biggerElems x (cdr xs)))
       (t
        (cons (car xs) (biggerElems x (cdr xs))))))

@لويس أوليفيرا

هذا الحل يتناقض مع الحل المنشور في السؤال.إذا كنا بحاجة إلى القيام بشيء أكثر تعقيدًا قليلاً، فمن المهم أن نعتمد على النهج التكراري لمعالجة القوائم.

@ بن:ليس استدعاء setf هو الخطأ - المشكلة هي أنه لا يقوم بتحديث XS.

أي:يتم تعيين xst على xs مع إزالة العنصر، ولكن لا يتم تحديث xs.إذا كان سيتم إزالة العنصر الثاني، فسيستعيد xst العنصر الأول مرة أخرى.

ستحتاج إلى ربط xst بـ xs، واستبدال xs في مكالمة الإزالة بـ xst.سيؤدي هذا بعد ذلك إلى إزالة كافة العناصر x أكبر منها.أي:

(defun biggerElems(x xs)
  (let ((xst xs))
    (dolist (elem xs)
      (when (> x elem)
        (setf xst (remove elem xst))))
    xst))

قد يكون من الأسرع قليلاً ضبط xst على (نسخ قائمة xs) ثم استخدام الحذف بدلاً من الإزالة (الحذف مدمر...اعتمادا على التنفيذ الخاص بك، قد يكون أسرع من الإزالة.نظرًا لأنك تتصل بهذا عدة مرات، فقد تحصل على أداء أفضل عند نسخ القائمة مرة واحدة والحذف منها بشكل مدمر).

بدلاً عن ذلك:

(defun bigger-elems (x xs) ; I prefer hyphen separated to camelCase... to each his own
  (loop for elem in xs when (<= x elem) collect elem))

إذا نظرنا إلى مشاركتك الأصلية، نجد أنها مربكة بعض الشيء...أنت تقول أنك تزيل جميع العناصر الأكبر من x، ولكن يبدو أن الكود الخاص بك يحاول إزالة جميع العناصر الأكبر من x.الحلول التي كتبتها تُرجع جميع العناصر الأكبر من x (على سبيل المثال:إزالة جميع العناصر x أكبر من).

ما هو "#" ل؟لم يتجمع معها.

خطأ مطبعي.عادة ما تشير إلى الوظائف مع #' (يحب (remove-if #'oddp list))، ولكن عندما كنت أقوم بالتحرير، نسيت إزالة "#".

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