Выровняйте список списков - PullRequest
1 голос
/ 30 марта 2019

Я пытаюсь выровнять в Racket список, составленный из списков и список списков.Исходный список выглядит следующим образом:

'(((a 1) (b 2)) (c 3) ((d 4) (e 5)))

Мне нужно, чтобы он был таким:

'((a 1) (b 2) (c 3) (d 4) (e 5))

Я пробовал с выравнивать, объединять и т. Д., И я получаю разные вещи, но не этот:

(define KK '(((a 1)(b 2))(c 3)((d 4)(e 5))))

(map(lambda(x)(if (list? x) x (list x)))(concatenate KK))

'((a 1) (b 2) (c) (3) (d 4) (e 5))

(map(lambda(x)x)(concatenate KK))

'((a 1) (b 2) c 3 (d 4) (e 5))

(map(lambda(x)(if (list? (car x)) (ormap(lambda(y)(when (list? y) y)) x) x))KK)

'((a 1) (c 3) (d 4))

(map(lambda(x)(if (list? (car x)) (andmap(lambda(y)(when (list? y) y)) x) 
x))KK)

'((b 2) (c 3) (e 5))

Чем ближе я подошел, тем последние два, но у меня пропущены значения, потому что это булева карта.Карта упаковывает результат в один список.

РЕДАКТИРОВАТЬ: Моя основная проблема заключается в том, что список создается функцией, которая в зависимости от ввода выводится в виде одного списка или списка от 2 до n списков:

Пусть список с именем H состоит из 2 или n элементов.Пусть SPECS будет списком, составленным из списков с возможными комбинациями элементов H, которые соответствуют условию C. Например:

H='(a 1)

Итак, будучи '* символом, который семантически означает дикий автомобиль, пустьвсе комбинации элементов в H должны быть:

HHs='((* *) (a *)(* 1) (a 1))

Таким образом, SPECS - это HH, которые удовлетворяют некоторым условиям, например: '((a ) ( 1))

(map (lambda(S)(when  (<condition>)(set! NEWSET (append NEWSET S))))SPECS)

Если я отслеживаю SI, вижу это:

S1: (((*) (-inf.0 9) (2 +inf.0) (*)) ((*) (9 30) (2 +inf.0) (*)))
S2: ((*) (-inf.0 30) (2 +inf.0) (*))
S3: (((*) (-inf.0 30) (2 +inf.0) (no)) ((*) (-inf.0 30) (2 +inf.0) (si)))
S4: (((soleado) (-inf.0 30) (*) (*)) ((nublado) (-inf.0 30) (*) (*)) ((lluvioso) (-inf.0 30) (*) (*)))

Так что, если я упакую их в список, у меня будет:

'((((*) (-inf.0 9) (2 +inf.0) (*)) ((*) (9 30) (2 +inf.0) (*)))
   ((*) (-inf.0 30) (2 +inf.0) (*))
   (((*) (-inf.0 30) (2 +inf.0) (no)) ((*) (-inf.0 30) (2 +inf.0) (si)))
   (((soleado) (-inf.0 30) (*) (*)) ((nublado) (-inf.0 30) (*) (*)) ((lluvioso) (-inf.0 30) (*) (*))))

Но мне нужно будет вместо:

'(((*) (-inf.0 9) (2 +inf.0) (*)) ((*) (9 30) (2 +inf.0) (*))((*) (-inf.0 30) (2 +inf.0) (*))((*) (-inf.0 30) (2 +inf.0) (no)) ((*) (-inf.0 30) (2 +inf.0) (si))((sunny) (-inf.0 30) (*) (*)) ((cloudy) (-inf.0 30) (*) (*)) ((rainy) (-inf.0 30) (*) (*)))

(наличие элементов списков в () - это просто семантика моего алгоритма).

С уважением

Ответы [ 3 ]

2 голосов
/ 31 марта 2019

Вот решение, которое использует match. Обратите внимание, что предположение здесь заключается в том, что внутренний список, который мы поднимаем, представляет собой список из 2 вещей.

#lang racket

(require rackunit)

(define (flat-lift l)
  (match (flatten l)
    ['() '()]
    [(cons a (cons b c)) (cons (list a b) (flat-lift c))]))

(check-equal? (flat-lift '(((a 1) (b 2)) (c 3) ((d 4) (e 5))))
              '((a 1) (b 2) (c 3) (d 4) (e 5)))

(check-equal? (flat-lift '((((((a 1))))))) '((a 1)))

(check-equal? (flat-lift '()) '())

(check-equal? (flat-lift '((a 1) (b 2) (c 3) (d 4) (e 5)))
              '((a 1) (b 2) (c 3) (d 4) (e 5)))
2 голосов
/ 30 марта 2019

Нет единой встроенной процедуры для решения этой проблемы в общем случае произвольно вложенного списка. Вот возможное решение с использованием явного цикла, при условии, что список содержит двухэлементные подсписки на всех уровнях:

(define (level-out lst)
  (let loop ([lst (flatten lst)])
    (if (empty? lst)
        '()
        (cons (list (first lst) (second lst))
              (loop (rest (rest lst)))))))

Работает как положено:

(level-out '(((a 1) (b 2)) (c 3) ((d 4) (e 5))))
=> '((a 1) (b 2) (c 3) (d 4) (e 5))

(level-out '((((((a 1)))))))
=> '((a 1))

(level-out '())
=> '()

(level-out '((a 1) (b 2) (c 3) (d 4) (e 5)))
=> '((a 1) (b 2) (c 3) (d 4) (e 5))
1 голос
/ 31 марта 2019

Если у вас есть предикат, который определяет, когда подсписок не должен быть сплющен, вы можете сделать это.

;; An Element is a value for which element? returns true
;; element? : Any -> Boolean
(define (element? v)
  ...you-have-to-determine-this...)

Этот предикат element? должен ответить на вопрос: "Что определяет, когда подсписок не должен быть сплющен?" Например, (z 0), (a 1), (b 2) и т. Д. Не сведены в ваших примерах. До сих пор в других ответах предполагалось, что это определяет двухэлементные списки, но вы сказали, что подсписки состоят из 1 - n элементов. Независимо от формы тех, которые отличают их от обычных вложенных списков, вы должны определить element?, чтобы распознать это.

Если вы определите этот предикат element?, тогда вы можете создать функцию сглаживания на его основе:

;; A NestedListofElement is one of:
;;  - Element
;;  - [Listof NestedListofElement]

;; flatten-elements : NestedListofElement -> [Listof Element]
(define (flatten-elements nle)
  (cond
    [(element? nle) (list nle)]
    [(list? nle)    (append-map flatten-elements nle)]))
...