Вы можете написать функцию all-equal?
следующим образом:
(define (all-equal? list)
;; (all-equal? '()) -> #t
;; (all-equal? '(35)) -> #t
;; (all-equal? '(2 3 2)) -> #f
(if (or (null? list) (null? (cdr list)))
#t
(reduce equal? list)
))
, затем сделать:
(all-equal? (map length listOfLists))
В качестве альтернативы вы можете сделать:
(define (lists-same-size? list-of-lists)
(if (== (length listOfLists) 0)
#t
(let*
(( firstLength
(length (car listOfLists)) )
( length-equal-to-first?
(lambda (x) (== (length x) firstLength)) )
)
(reduce and #t (map length-equal-to-first? listOfLists))
)
)))
Что это говорит о том, что: если длина списка равна 0, наше утверждение пусто верно, в противном случае мы фиксируем первый элемент длины списка (в части 'else' * -22-предложения), помещаем его взамыкание, определенное синтаксическим сахаром let
(на самом деле лямбда), и использование его для определения функции length-equal-to-first?
.
К сожалению reduce
не ленив.Что нам действительно нужно, так это избегать вычисления длин списков, если мы обнаружим, что только один не равен.Таким образом, чтобы быть более эффективным, мы могли бы сделать:
...
(let*
...
( all-match? ;; lazy
(lambda (pred list)
(if (null? list)
#t
(and (pred (first list)) (all-match? (cdr list)))
;;^^^^^^^^^^^^^^^^^^^ stops recursion if this is false
)) )
)
(all-match? length-equal-to-first? listOfLists)
)
)))
Обратите внимание, что all-match?
уже эффективно определено для вас с (list-search-positive list pred)
или (for-all? list pred)
схемы MIT или в Racket как andmap
.
Почему запись занимает так много времени?
Вы вынуждены писать базовый вариант, потому что ваше сокращение не имеет канонического элемента, поскольку оно опирается на первыйЭлемент и список манипуляций в большинстве языков не очень мощные.У вас даже будет такая же проблема в других языках, таких как Python.В случае, если это помогает:
второй метод:
if len(listOfLists)==0:
return True
else:
firstLength = len(listOfLists[0])
return all(len(x)==firstLength for x in listOfLists)
Однако первый метод намного проще писать на любом языке, потому что он обходит эту проблему, игнорируя базовые случаи.
первый метод:
if len(listOfLists)<2:
return True
else:
return reduce(lambda a,b: a==b, listOfLists)